top | item 28116888

The World of CSS Transforms

294 points| joshwcomeau | 4 years ago |joshwcomeau.com | reply

70 comments

order
[+] bobbylarrybobby|4 years ago|reply
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.

[+] joshwcomeau|4 years ago|reply
Oh! This is a helpful insight, thanks. Updating the blog post.
[+] userbinator|4 years ago|reply
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.
[+] aenis|4 years ago|reply
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.

[+] hoten|4 years ago|reply
> 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].

[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
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.

[+] Blikkentrekker|4 years ago|reply
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.

[+] rchaud|4 years ago|reply
Bookmarked!

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
What did people do before CSS transforms?

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
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.

[+] armandososa|4 years ago|reply
We mostly used boxy layouts, sliced up images and flash hacks.
[+] legrande|4 years ago|reply
> What did people do before CSS transforms?

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
So nice to see an actual personal blog not on Medium, nice design too.
[+] simonw|4 years ago|reply
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.

[+] dmitriid|4 years ago|reply
> 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.

[+] runawaybottle|4 years ago|reply
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).
[+] divbzero|4 years ago|reply
Noteworthy tidbit about percent values:

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
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.

[+] tintt|4 years ago|reply
Nice, didn’t know that one
[+] dustinlakin|4 years ago|reply
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.
[+] mahoro|4 years ago|reply
Wow I love this tutorial! It helps to build better connections between enormous tools that CSS provides. As a newbie frontend dev I feel lost in them.

Thanks, Josh!

[+] vsareto|4 years ago|reply
Anyone know if scale(0) shares any properties with the other methods to hide things in CSS? https://stackoverflow.com/a/34529598

I'm guessing it still takes space, is in flow, and takes clicks?

[+] maskros|4 years ago|reply
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.
[+] macando|4 years ago|reply
This shows how powerful modern CSS is.

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
> This is incredibly handy when we want an element to sit just outside another one

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
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.
[+] evanreichard|4 years ago|reply
Interactive demo doesn't appear to work on Firefox?
[+] smbv|4 years ago|reply
Works just fine for me.
[+] joshwcomeau|4 years ago|reply
Appreciate the heads-up — Which version and OS? And is it all of the interactive demos, or only some of them?
[+] dheera|4 years ago|reply
> 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

[+] reidjs|4 years ago|reply
Thanks for all of your classes and tutorials, Josh, they really help me understand how to use CSS to get stuff done.
[+] tintt|4 years ago|reply
It’s cool, but 2D transformations are easy to wrap your head around anyway. Waiting for part two!
[+] jordache|4 years ago|reply
Do people still regard CSS transform as a solid strategy to invoke GPU powered UI updates?