I have side-by-side buttons that are shaped like arrows. In order to achieve this, I am using the ::before and ::after pseudoelements to create rotated squares. They look great, until I try to animate a button. The problem is that the tip of the arrow to the right (::after) must overlap the white square creating the negative/white space behind the next arrow's left edge. I do that by making the ::after square z-index:1, and it works fine. But, when I try to apply a transform to the button in an animation, it breaks the stacking context of the ::before and ::after pseudo elements.
I created a fiddle to demonstrate: https://jsfiddle.net/twnrov23/
<button type="button" class="btn btn-info btn-arrow-right" >1. Step 1</button>
<button type="button" id="button2" class="btn btn-info btn-arrow-right" >2. Step 2</button>
<button type="button" class="btn btn-info btn-arrow-right" >3. Step 3</button>
/* ANIMATION */
.wiggle{
animation: wiggle 2s linear 1;
}
@keyframes wiggle {
0%, 7% {
transform: rotateZ(0);
}
15% {
transform: rotateZ(-15deg);
}
20% {
transform: rotateZ(10deg);
}
25% {
transform: rotateZ(-10deg);
}
30% {
transform: rotateZ(6deg);
}
35% {
transform: rotateZ(-4deg);
}
40%, 100% {
transform: rotateZ(0);
}
}
/* ARROW BUTTONS */
.btn {
line-height: 1.25;
}
.btn-arrow-right,
.btn-arrow-left {
position: relative;
padding-left: 18px;
padding-right: 18px;
}
.btn-arrow-right {
padding-left: 36px;
}
.btn-arrow-left {
padding-right: 36px;
}
.btn-arrow-right::before,
.btn-arrow-right::after,
.btn-arrow-left::before,
.btn-arrow-left::after { /* make two squares (before and after), looking similar to the button */
display: inline-block;
content: "";
position: absolute;
top: 5px; /* move it down because of rounded corners */
width: 22px; /* same as height */
height: 22px; /* button_outer_height / sqrt(2) */
background: inherit; /* use parent background */
border: inherit; /* use parent border */
border-left-color: transparent; /* hide left border */
border-bottom-color: transparent; /* hide bottom border */
border-radius: 0px 4px 0px 0px; /* round arrow corner, the shorthand property doesn't accept "inherit" so it is set to 4px */
-webkit-border-radius: 0px 4px 0px 0px;
-moz-border-radius: 0px 4px 0px 0px;
}
.btn-arrow-right::before,
.btn-arrow-right::after {
transform: rotate(45deg); /* rotate right arrow squares 45 deg to point right */
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
}
.btn-arrow-left::before,
.btn-arrow-left::after {
transform: rotate(225deg); /* rotate left arrow squares 225 deg to point left */
-webkit-transform: rotate(225deg);
-moz-transform: rotate(225deg);
-o-transform: rotate(225deg);
-ms-transform: rotate(225deg);
}
.btn-arrow-right::before,
.btn-arrow-left::before { /* align the "before" square to the left */
left: -11px;
}
.btn-arrow-right::after,
.btn-arrow-left::after { /* align the "after" square to the right */
right: -11px;
}
.btn-arrow-right::after,
.btn-arrow-left::before { /* bring arrow pointers to front */
z-index: 1;
}
.btn-arrow-right::before,
.btn-arrow-left::after { /* hide arrow tails background */
background-color: white;
}
When the wiggle class is applied to #button2, the z-index of the ::before and ::after elements is broken.
EDIT 1: If I apply a z-index to each button, where button 1 has z-index 3, button 2 has z-index 2, and button 3 has z-index 1, then it works. Obviously that isn't a great solution because it will require inline css.