I got a weird 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 happens when I use the .bad
div (remove .good
div) then the gray background which contains the camera-icon does not lay inside the circle image.
If I remove the animation transform
in CSS, the button won't pulse anymore but the gray background will be inside circle image.
Anyone know what it is and how to solve it?
This problem is quite similar to the one that I had answered earlier. The reason why the gray box with the camera icon is not contained within the circle (not cropped by the circle) is because of how layers are created and accelerated rendering is performed by browsers. You can find more information about it in the answer that I had linked earlier.
Solution:
The solution to your problem would be to move the pulsing buttons to a layer higher by setting a higher z-index
value to it. In the below snippet, I have 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 a z-index
for the #box_avatar
would also solve the issue.
Reason:
Rendering and compositing are tricky to explain but the following is what happens when no z-index
or z-index: 0
is set to the a.abc
:
a.abc
gets its own rendering and compositing layer because it has an animated transform and explicit positioning properties. #box_avatar
and #bg_gray
also get their own compositing layer. The #box_avatar
seems to be getting a separate layer because it has a previous sibling with equal or lower z-index
.#bg_gray
gets a separate layer but it seems to mostly be because of how z-index: auto
creates a separate stacking context. (Source - W3C Spec)When distinct layers are created for #box_avatar
, #bg_gray
and they are placed one on top of the other, the #bg_gray
isn't exactly inside the #box_avatar
and so doesn't respect the overflow
and border-radius
. It is kind of like placing two layers of paper one on top of the other.
Detailed Explanation of Solution:
When z-index: 1
is assigned on a.abc
element:
a.abc
gets its own rendering and compositing layer because it has an animated transform.a.abc
also gets its layer because it has a child which has a compositing layer.#box_avatar
nor #bg_gray
get a separate compositing layer because they don't meet any of the criteria defined to get a compositing layer.When z-index: 0
is assigned on a.abc
and z-index: 1
is assigned on #box_avatar
:
a.abc
gets its own rendering and compositing layer because it has an animated transforma.abc
also gets its layer because it has a child which has a compositing layer#box_avatar
gets its own rendering and compositing layer because it has a sibling (a.abc
element's container) which has a compositing layer with lower z-index
.#bg_gray
becomes a part of the #box_avatar
element's layer and gets no separate layer.In both the above cases, because the #box_avatar
and #bg_gray
don't get separate layers, they are kind of painted together and so the #bg_gray
knows where to get cropped.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With