A Trick: Individual CSS Transform Functions
We get a lot of power through the single
transform property in CSS - allowing us to rotate, translate, scale, and more all at once. But allowing all of those different transform functions into one property can trip us up.
It’s common to want to apply different transforms to different states of our elements. Say we have a button that we always want to be translated
-150% vertically. When a user hovers over the button we scale the button down a bit, and on press (the active state) we rotate it 180 degrees. This example shows how one might first think to write the CSS for “My Button” as just described, and then the “Expected” button shows a way to get it as intended.
With the initial styles on the button we are not just adding the scale on hover… we are overriding the original translate as well, so it scales and transitions back to
Why is this? Linear Algebra. The way these transformations happen depend on each other and their order (such that
translate(-50%, -50%) scale(.4) rotate(50deg) is different than
rotate(50deg) translate(-50%, -50%) scale(.4)), and they boil down to matrix multiplication. But we usually don’t need to know transforms at that level. Web developers just want to know how they can maintain these transform functions at an individual level.
Chrome has begun implementing individual properties, such that
scale become first class properties as seen in this previous example (as of this writing requires Chrome Canary). But this has limitations of its own:
zpieces of each are still tied to a single property currently.
- The order will always be
translate scale rotatewhen it is converted to matrices.
- Early days - just in Chrome Canary.
So what can we do?
Use CSS Variables.
Listening to David Khourshid talk about CSS Variables quickly opened my eyes to a lot of opportunities for animating with them. It wasn’t until I started putting variables everywhere that their power became even clearer. Without further ado… here is the trick to give us more flexibility (with the how/what/why after the example).
We set up a key initial
Without the CSS variables we would have to do some calculations on the current transition when changing one of the transform functions (which may not be trivial). Then we could know where the other two functions are currently to make sure the transition remained smooth. Every time a variable is changed, a new transition occurs in the same way as if you had rewritten the
transform property from scratch, so you still can’t have different transitions for each transform function.
How does this compare to the upcoming individual properties in Chrome Canary?
- We can do any combination of
zsince we choose how to set up our initial
- Similarly, we can even do whatever order of the transform functions we want (though we lose the (likely) less common use case of changing the order around between states).
- I’ve seen this work well in latest Chrome (56), Firefox (50), and Safari (Technical Preview only - Safari 10 supports variables but will not do a smooth transition). I’ve not been able to test Edge Insider Preview yet (which is the first version to support CSS Variables) - so please reach out if you have information on that front.
And please reach out if you have some creative uses for this technique.