Border radius and overflow are not respected when animation is added to another element

I had strange behavior when working with transform in CSS3.

Here is my code:

 *, *:before, *:after { box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; } .btn_exchange a { position: relative; text-decoration: none; display: block; width: 150px; float: left; color: #ffffff; font-size: 14px; background: #0ea2d3; box-shadow: 0 3px 0 0 rgba(7, 154, 190, 0.75); text-align: center; font-weight: bold; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @-webkit-keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } a.abc { z-index: 0; -webkit-animation: pulse 1s linear 0s infinite alternate; animation: pulse 1s linear infinite; } #box_avatar { position: relative; margin: 0 auto; -webkit-border-radius: 62.5px; -moz-border-radius: 62.5px; -ms-border-radius: 62.5px; -o-border-radius: 62.5px; border-radius: 62.5px; width: 125px; height: 125px; border: 2px solid #ccc; display: block; overflow: hidden; } #img_avatar { width: 125px; height: 125px; cursor: pointer; border-radius: 62.5px; } #bg_gray { background: #4c4747; width: 100%; position: absolute; bottom: 0; padding: 8px 0 10px 0; opacity: 0.8; } #bg_gray img { display: block; width: 20px; margin: 0 auto; } 
 <div class="btn_exchange fl bad"> <a class="button abc" href="#">Button</a> </div> <div id="box_avatar"> <img id="img_avatar" src="http://i.imgur.com/O29DJOZ.jpg" alt="avatar" /> <div id="bg_gray"> <img src="http://i.imgur.com/m5qIRID.png" alt="btn_camera" /> </div> </div> <div class="btn_exchange fl good"> <a class="button abc" href="#">Button</a> </div> 

The problem occurs when I use the .bad div (remove the .good div), then the gray background containing the camera icon does not lie inside the circle image.

If I remove the transform animation in CSS, the button will no longer pulsate, and the gray background will be inside the circle image.

Does anyone know what it is and how to solve it?

+7
html css css3 css-transforms css-animations
source share
2 answers

This problem is very similar to the one I answered earlier . The reason that the gray square with the camera icon is not contained in the circle (not cropped by the circle) is due to the way the layers are created and accelerated rendering is done by browsers. You can find more information about this in the answer I linked earlier.

Decision:

The solution to your problem was to move the pulsating buttons one level higher by setting a higher z-index value for it. In the snippet below, I set it to 1, and you can see that it solves the problem.

 *, *:before, *:after { box-sizing: border-box; } .btn_exchange a { position: relative; display: block; float: left; width: 150px; color: #ffffff; font-size: 14px; text-decoration: none; text-align: center; font-weight: bold; background: #0ea2d3; box-shadow: 0 3px 0 0 rgba(7, 154, 190, 0.75); } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } a.abc { z-index: 1; animation: pulse 1s linear infinite; } #box_avatar { position: relative; display: block; width: 125px; height: 125px; margin: 0 auto; border-radius: 62.5px; border: 2px solid #ccc; overflow: hidden; } #img_avatar { width: 125px; height: 125px; border-radius: 62.5px; cursor: pointer; } #bg_gray { position: absolute; width: 100%; bottom: 0; padding: 8px 0 10px 0; background: #4c4747; opacity: 0.8; } #bg_gray img { display: block; width: 20px; margin: 0 auto; } 
 <div class="btn_exchange fl bad"> <a class="button abc" href="#">Button</a> </div> <div id="box_avatar"> <img id="img_avatar" src="http://i.imgur.com/O29DJOZ.jpg" alt="avatar" /> <div id="bg_gray"> <img src="http://i.imgur.com/m5qIRID.png" alt="btn_camera" /> </div> </div> <div class="btn_exchange fl good"> <a class="button abc" href="#">Button</a> </div> 

Applying z-index to #box_avatar will also solve the problem.


Cause:

Rendering and layout are hard to explain, but the following happens when z-index or z-index: 0 set to a.abc :

  • a.abc gets its own rendering and layout layer because it has animated transforms and explicit positioning properties.
  • The process of creating a rendering and layout layer is explained in this article . These layers can be seen by turning on the Show Coloring Edges and Show Compiled Layer Borders tools in the Dev tools.
  • #box_avatar and #bg_gray also get their own composition layer. It seems that #box_avatar getting a separate layer because it has a previous sibling with equal or less z-index .
  • I can’t pinpoint why #bg_gray gets a separate layer, but it seems that this is mainly due to the way z-index: auto creates a separate stacking context. ( Source - W3C Specification )

When separate layers are created for #box_avatar , #bg_gray and they are located one on top of the other, #bg_gray is not quite inside #box_avatar and therefore does not take into account overflow and border-radius . This is like placing two layers of paper on top of each other.


Detailed explanation of the solution:

When z-index: 1 is assigned on a.abc element:

  • a.abc gets its own rendering and layout layer because it has an animated transform.
  • The a.abc container also gets its layer because it has a child that has a composition layer.
  • Neither #box_avatar nor #bg_gray receive a separate layout layer because they do not meet any of the criteria defined to obtain the composition layer.

When z-index: 0 is assigned to a.abc and z-index: 1 is assigned to #box_avatar :

  • a.abc gets its own render and layout layer because it has an animated transform
  • The a.abc container also gets its layer because it has a child that has a composition layer
  • #box_avatar gets its own rendering and layout layer because it has an element container ( a.abc ) that has a composition layer with a lower z-index .
  • #bg_gray becomes part of the layer of the #box_avatar element and does not receive a separate layer.

In both cases, since #box_avatar and #bg_gray do not receive separate layers, they are as if painted together, so #bg_gray knows where to crop.

+7
source share

I looked and can’t understand why it behaves this way, so it would be nice if you skip the img element and use a background image instead?

If so, here is an example that works.

Another option is to combine background and pseudo instead of img . This will give you a clearer html structure and also solve your problem.

 *, *:before, *:after { box-sizing: border-box; } .btn_exchange a { position: relative; text-decoration: none; display: block; width: 150px; float: left; color: #ffffff; font-size: 14px; background: #0ea2d3; box-shadow: 0 3px 0 0 rgba(7, 154, 190, 0.75); text-align: center; font-weight: bold; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @-webkit-keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } a.abc { z-index: 0; animation: pulse 1s linear infinite; } #box_avatar { position: relative; margin: 0 auto; border-radius: 62.5px; width: 125px; height: 125px; border: 2px solid #ccc; display: block; overflow: hidden; background: url(http://i.imgur.com/O29DJOZ.jpg); cursor: pointer; } #bg_gray { bottom: 0; left: 0; width: 100%; height: 30px; position: absolute; overflow: hidden; cursor: auto; } #bg_gray:before { content: ""; background: #4c4747; width: 100%; height: 125px; bottom: 0; position: absolute; opacity: 0.8; border-radius: 62.5px; } #bg_gray:after { content: ""; width: 100%; height: 30px; bottom: 0; position: absolute; background: url(http://i.imgur.com/m5qIRID.png) center center no-repeat; background-size: 20px; } 
 <div class="btn_exchange fl bad"> <a class="button abc" href="#">Button</a> </div> <div id="box_avatar"> <div id="bg_gray"></div> </div> <div class="btn_exchange fl good"> <a class="button abc" href="#">Button</a> </div> 
0
source share

All Articles