Introduction
I wrote about making a small CSS animation for a left to right transition, but it turns out it's a pretty bad way of doing things. So! Live and learn! It turns out that when you animate the left
position of an element (for instance) some problems come up.
- It doesn't allow for the
will-change
property - You end up re-rendering the whole page
- You can't push the animation off to the GPU
The better way is to use CSS transforms.
Transformers!
The transform CSS property lets you rotate, scale, skew, or translate an element. It modifies the coordinate space of the CSS visual formatting model.
In this particular case, the goal was to make the blue box appear to shrink to reveal a red background.
Translate
I tried transform: translateX
which produced a cool effect, but not the one the designers asked for. It moved the entire blue area from left to right. When I transitioned the opacity
I ended up liking it a lot. If you like, you can see it here.
Scale
Instead, the transform required is scale
. When used by itself, it scales both the X and Y (and possibly even Z) axes of the item. It takes numbers such as
scale(0)
scale(0.5)
scale(4)
etc...
This makes it perfect for combining with the transition
property. Even better is that you can specify that only the X (or Y) axis gets the transformation by using scaleX
.
In this case, I ended up switching which element was going to change from the previous example and how the z-index
is applied.
a:before,
a:after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
a:before {
background-color: #000e2f;
z-index: -2;
}
a:after {
background-color: red;
z-index: -1;
transform-origin: left;
transform: scaleX(0);
transition: transform 0.3s ease-in-out;
}
This puts the red "background" in front of the blue background while the text stays in front of both. The :after
selector has transform: scaleX(0)
which effectively gives it no size even though it's positioned to take up the full size of the element. At the same time it has the transition
property applied to prepare the elements to move.
On hover
or focus
the :after
element gets
a:hover:after,
a:focus:after {
transform: scalex(1);
will-change: transform;
}
This will make the element appear to grow or shrink over 0.3 seconds. The will-change
property makes sure that the animation is pushed off to the GPU and that it doesn't effect the whole page.
Conclusion
All in all, this is a much better way of handling the animation. It's much more efficient and appears significantly smoother than the previous approach.