Great article, but one nit: order of transforms matters, yes, but you’re supposed to read them right to left (like matrix multiplication).
When you have `transform: translateX(…) rotate(…);`, you’re saying “first rotate it about the origin, then translate it”. When you have `transform: rotate(…) translateX(…);`, you’re saying “first translate it, then rotate it about the origin”! — not the translated object’s origin! That’s why in the the second example the transformed object swings around the origin from a distance when you change the rotation angle.
I mean, sure, you can mentally do it left to right and track how the axes change, as the author did, but right to left is a lot simpler, and is what’s actually happening to the vectors behind the scenes.
You can think of the transforms as function applications to more easily remember the order: translate rotate foo -> translate(rotate(foo)), i.e. do the rotation and then translate the result of it.
Coming from a person who started writing UIs back in the 1980's, where one needed good assembly code to be able to do display text files in text mode, I am seriously impressed how effective browsers are in rendering HTML/CSS.
For a bunch of scripting languages stacked on top of each other, with byzantine levels of backwards compatibility and alternative ways to define the same things, thats seriously impressive optimisation techniques in the browsers. And they are pretty consistent, too. Absolutely awesome.
Of course, I am sure it generates a lot of CO2 for all that effortless eyecandy.
> I am sure it generates a lot of CO2 for all that effortless eyecandy.
Why?
Genuine question. A couple years ago I tried assessing the claim that websites (frontend, specifically) can meaningfully be tuned to reduce emissions [1]. Apparently it takes less than a dollar/year (2018) to charge a smartphone (0 to 100% daily) [2]. Given that fact, and assuming that energy usage from a mobile browser is in the same order of magnitude as a desktop browser + price is a decent stand-in for amount of emissions, it seems to me that any savings aimed at reducing emissions via "better" websites is negligible, even at web scale. I have a simple (maybe too simple?) spreadsheet to back this up [3].
I am sure it generates a lot of CO2 for all that effortless eyecandy
Maybe, but many people have optimized the browser layout engines to make them efficient. That probably means they're far more efficient that the sorts of UIs people write themselves, despite several layers of abstraction. One badly written block of code can waste a lot of energy.
I'm more so concerned for the fact that browsers are required to be so complex that it is seemingly more complicated to write a web browser rendering engine than a video game engine.
The resources modern browsers require to run are silly and often take more resources than all other applications combine, and small players have a hard time entering the field.
I know CSS transforms relatively well, but there's just no substitute for a well-explained web page with interactive demos!
Another similarly laid out web page I find myself going to is a Flexbox tutorial with demos, and toggles that show the difference between flex properties. [0]
I've been making an app with React Native and react-native-svg and even though react-native-svg supports transformations, I've had to do a lot of transforms with trigonometry (i.e. rotating a shape around a center point, then getting the new bounding box, which requires things such as Math.atan2).
It's made me really appreciate 1. how much easier front end web development is and 2. how far we've gotten. I cannot tell you how much I appreciate web methods like getBoundingClientRect() or element.closest(), and how easy it is to make animations with CSS and move things around with transforms.
I mean, CSS transforms aren't really that useful for regular static layout webpages, so people didn't mostly need them.
Probably the main thing they're most useful for is animation, and people just used jQuery/JavaScript for that instead, which could do most of what you'd want, if a little clunky.
They used Flash. You can now do everything you could do in Flash, with CSS[0]. There's even a few GUI tools[1] for CSS where you don't have to figure out the code:
This was great - I found the interactive demos really useful and I picked up some good new information from the extra context provided for each transform.
I hadn't clocked how useful it is that percentage for translate() means the element itself, not it's parent container for example.
> Critically, the item's in-flow position doesn't change.
This is the main problem with animations in CSS: they work as long as you don't have to reflow the document, and `transform: translate` is very good for that.
But try to slide a new item into a list (or animate as it's being removed), and you're in for a nasty surprise especially if you don't know the height of the element beforehand.
Always pop stuff out with position absolute. It sucks to have to know top, bottom positioning, but it’s the only way to get smoother animations (pop it out of the document flow).
It's unique because in any other context, defining an element's size in terms of its size would be circular. But the transform property works differently: the rendered size is independent from the element's "real" DOM size. This can be seen in the fact that transform doesn't change the flow of the document at all; there's an invisible placeholder element that's still taking up the same space, and only its visual representation is changed. So the latter can be derived from the former without a circular effect. This is also the reason browsers can offload the transform property to the GPU.
Something I love to do with this is create "squishy" buttons that transform:scale(0.9) when under the :active pseudo-class (with a short transition set up for smooth animation). It's extra satisfying on touchscreens.
Excellent content Josh! Something about being able to adjust knobs makes me enjoy diving deep into a subject. I am excited for more of your course/posts.
It takes the same space in the flow as if not transformed, but it will take clicks and other mouse events using the transformed size and position. In your example table, transform:scale(0) will behave like visibility:hidden.
I too was surprised to discover that the order of transform params matters. Until I swapped them I was getting a completely different and unwanted animation effect.
Golden rule of web dev: If you can do it in CSS, do it in CSS.
I love this guy's blog. I've been learning so much about modern CSS from it. I highly suggest anyone who wants to get up to speed on this to check out his mailing list.
> used the transform property more than 350 times!
Of course.
-webkit-transform, -o-transform, -ms-transform, -moz-transform, -e-transform, -some-other-bullshit-browser-transform, -khtml-transform, -html-transform ... welcome back to the 90's world of brower-specific-internet
You can do 3d with CSS but to my knowledge there's no way to apply lighting and that, to me, is the real deal breaker. Otherwise people would've done all kinds of unnecessary but cool demos just for the sake of it.
[+] [-] bobbylarrybobby|4 years ago|reply
When you have `transform: translateX(…) rotate(…);`, you’re saying “first rotate it about the origin, then translate it”. When you have `transform: rotate(…) translateX(…);`, you’re saying “first translate it, then rotate it about the origin”! — not the translated object’s origin! That’s why in the the second example the transformed object swings around the origin from a distance when you change the rotation angle.
I mean, sure, you can mentally do it left to right and track how the axes change, as the author did, but right to left is a lot simpler, and is what’s actually happening to the vectors behind the scenes.
[+] [-] joshwcomeau|4 years ago|reply
[+] [-] userbinator|4 years ago|reply
[+] [-] aenis|4 years ago|reply
For a bunch of scripting languages stacked on top of each other, with byzantine levels of backwards compatibility and alternative ways to define the same things, thats seriously impressive optimisation techniques in the browsers. And they are pretty consistent, too. Absolutely awesome.
Of course, I am sure it generates a lot of CO2 for all that effortless eyecandy.
[+] [-] hoten|4 years ago|reply
Why?
Genuine question. A couple years ago I tried assessing the claim that websites (frontend, specifically) can meaningfully be tuned to reduce emissions [1]. Apparently it takes less than a dollar/year (2018) to charge a smartphone (0 to 100% daily) [2]. Given that fact, and assuming that energy usage from a mobile browser is in the same order of magnitude as a desktop browser + price is a decent stand-in for amount of emissions, it seems to me that any savings aimed at reducing emissions via "better" websites is negligible, even at web scale. I have a simple (maybe too simple?) spreadsheet to back this up [3].
[1] https://github.com/thegreenwebfoundation/lighthouse-plugin-g...
[2] https://www.zdnet.com/article/heres-how-much-it-costs-to-cha...
[3] https://docs.google.com/spreadsheets/d/18cNY8Xpabau3bMY5iEsB...
[+] [-] onion2k|4 years ago|reply
Maybe, but many people have optimized the browser layout engines to make them efficient. That probably means they're far more efficient that the sorts of UIs people write themselves, despite several layers of abstraction. One badly written block of code can waste a lot of energy.
[+] [-] Blikkentrekker|4 years ago|reply
The resources modern browsers require to run are silly and often take more resources than all other applications combine, and small players have a hard time entering the field.
[+] [-] rchaud|4 years ago|reply
I know CSS transforms relatively well, but there's just no substitute for a well-explained web page with interactive demos!
Another similarly laid out web page I find myself going to is a Flexbox tutorial with demos, and toggles that show the difference between flex properties. [0]
[0] https://www.codeinwp.com/blog/css-flexbox-tutorial/
[+] [-] orangegreen|4 years ago|reply
I've been making an app with React Native and react-native-svg and even though react-native-svg supports transformations, I've had to do a lot of transforms with trigonometry (i.e. rotating a shape around a center point, then getting the new bounding box, which requires things such as Math.atan2).
It's made me really appreciate 1. how much easier front end web development is and 2. how far we've gotten. I cannot tell you how much I appreciate web methods like getBoundingClientRect() or element.closest(), and how easy it is to make animations with CSS and move things around with transforms.
[+] [-] crazygringo|4 years ago|reply
Probably the main thing they're most useful for is animation, and people just used jQuery/JavaScript for that instead, which could do most of what you'd want, if a little clunky.
[+] [-] dmitriid|4 years ago|reply
What sibling comments said, and also jQuery helper functions such as $.fade [1] or GSAP [2]
[1] https://api.jquery.com/fadeIn/#fadeIn-duration-complete
[2] https://greensock.com/gsap/
[+] [-] armandososa|4 years ago|reply
[+] [-] legrande|4 years ago|reply
They used Flash. You can now do everything you could do in Flash, with CSS[0]. There's even a few GUI tools[1] for CSS where you don't have to figure out the code:
[1] https://enjoycss.com/
[1] http://selfcss.org/
[0] Edit: And Javascript
[+] [-] pupppet|4 years ago|reply
[+] [-] simonw|4 years ago|reply
I hadn't clocked how useful it is that percentage for translate() means the element itself, not it's parent container for example.
[+] [-] dmitriid|4 years ago|reply
This is the main problem with animations in CSS: they work as long as you don't have to reflow the document, and `transform: translate` is very good for that.
But try to slide a new item into a list (or animate as it's being removed), and you're in for a nasty surprise especially if you don't know the height of the element beforehand.
[+] [-] runawaybottle|4 years ago|reply
[+] [-] divbzero|4 years ago|reply
There's one thing that makes translate ridiculously powerful, though. Something totally unique in the CSS language.
When we use a percentage value in translate, that percentage refers to the element's own size, not the available space within the parent container.
[+] [-] brundolf|4 years ago|reply
Something I love to do with this is create "squishy" buttons that transform:scale(0.9) when under the :active pseudo-class (with a short transition set up for smooth animation). It's extra satisfying on touchscreens.
[+] [-] tintt|4 years ago|reply
[+] [-] dustinlakin|4 years ago|reply
[+] [-] mahoro|4 years ago|reply
Thanks, Josh!
[+] [-] vsareto|4 years ago|reply
I'm guessing it still takes space, is in flow, and takes clicks?
[+] [-] maskros|4 years ago|reply
[+] [-] macando|4 years ago|reply
I too was surprised to discover that the order of transform params matters. Until I swapped them I was getting a completely different and unwanted animation effect.
Golden rule of web dev: If you can do it in CSS, do it in CSS.
[+] [-] _greim_|4 years ago|reply
Nice! I've been using `position: absolute` + `bottom: 100%` for this. I'll be adding this trick to my toolbox.
[+] [-] jamal-kumar|4 years ago|reply
[+] [-] evanreichard|4 years ago|reply
[+] [-] smbv|4 years ago|reply
[+] [-] joshwcomeau|4 years ago|reply
[+] [-] unknown|4 years ago|reply
[deleted]
[+] [-] dheera|4 years ago|reply
Of course.
-webkit-transform, -o-transform, -ms-transform, -moz-transform, -e-transform, -some-other-bullshit-browser-transform, -khtml-transform, -html-transform ... welcome back to the 90's world of brower-specific-internet
[+] [-] oblak|4 years ago|reply
[+] [-] ilaksh|4 years ago|reply
[+] [-] reidjs|4 years ago|reply
[+] [-] tintt|4 years ago|reply
[+] [-] jordache|4 years ago|reply