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].
"assuming that energy usage from a mobile browser is in the same order of magnitude as a desktop browser"
Any basis for this assumption?
Desktop processors are much less optimized for power consumption, and desktop browsers are also used differently with websites often time left running in the background tab, compared to the mobile phone.
I think the claim is accurate only because I've set the bar quite low (10x being an order of magnitude).
But I'll do a similar analysis: how much does a constantly-used desktop PC emit? I'm seeing estimates of ~200 kg emissions/year from a desktop PC for ~8hr/day usage, which is ~0.4% of the average American's emissions (50,000 kg/year). Now you must consider some other things:
1) of those relatively small emissions, how much is due to energy that is used for baseline PC functions (OS, monitor, etc).
2) does idle time from a browser doing slightly less work translate to noticeably less power draw? I can see a difference from 100% to 80% CPU utilization, but what about 40% to 20%? is the relationship between cpu utilization and power draw linear?
3) I'd bet the largest offenders of sites in terms of power usage are complex webapps that have no meaningful room for performance improvements possible by a frontend developer: games, photo editors, video players. Compare to those, better CSS selectors seems small potatoes.
To be clear, my claim is that overall the savings here are negligible and efforts are far best spent elsewhere (extreme example: instead of a programmer trying to optimize even a heavily-trafficked site, they would have a larger impact if they spent their time ensuring their home, or the home of their friends and family, is not wasting energy).
That doesn't take into account the production footprint of a device capable to render today's web with all its transitions and glory, the environmental and geo-political toll on extracting lithium, rare earths, and other materials, plus the footprint of delivering devices into the hands of users, and disposal after typically only two years of usage.
Whereas had we been sticking to deliver just plain passive HTML markup users are after, we could've had solar-/light-powered devices with slow LCD displays and low-power RF transmission similar to old e-book readers by now (solar-powered pocket calculators were available in the 1970s already).
Would help with tracking, privacy, ad monopolies, and browser obsolescence as well.
Yes, but having our modern devices isn't solely to allow css to exist - good hardware allows devices to be a replacement for maps and gps, cameras, messaging systems, mobile games, entertainment systems, and everything else you can write an app for. Low power e-book readers exist, but it's clear that most people would much rather have a smartphone.
The focus of this analysis is if creating tooling and researching better frontend practices could result in a meaningful reduction of emissions. Saying "don't use the web at all or the devices that access it" is not very useful in this context.
Yes, I think you are right - I was half joking. Its unlikely the faster websites would free up enough idle cpu time to make up for all that extra time it would take to implement the web with lower level, presumably more efficient frameworks.
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.
You're comparing a value against a spectrum - there are a few video games that likely rival the complexity of a browser... but I don't know if it's really a fair comparison. Video games just do the one thing - while browsers are essentially mini-operating systems. Some folks primarily use GoogleDocs as their text editor.
I don't know if there was ever a time when browsers weren't heavier to write than games - except back in the dark days when the web was but a baby.
> while browsers are essentially mini-operating systems. Some folks primarily use GoogleDocs as their text editor.
The mini operating system is written in another language than the browser.
An analogy here would be writing such an operating system within the game engine, and then claiming the game engine that is only used to render the operating system is the operating system.
The real issue with browsers is the load of historical cruft they have to continue to support, as well as many new and duplicated technologies such as in this case C.S.S encroaching more and more upon the domain of browser scripting.
> I don't know if there was ever a time when browsers weren't heavier to write than games - except back in the dark days when the web was but a baby.
Is that really so? I would say that at the time game rendering technology was making vast advances in 3.d. rendering with clever hacks around the turn of the millennium, browsers were probably easier to write than these engines.
At least in my mind the nascent days of the web was the early 90's when a large portion of games were still mostly text based with most of the graphical fidelity coming from clever uses of flat 2D images that had sprites overlaid on them. You certainly had 3D games going back to 1981 - but there were still quite rare compared to isometric 2.5d games.
Even the side scrolling games of the early 90s required ingenious hacks to make them work on the hardware of the time.
Game consoles at the time had hardware accelerated sprite scrolling; personal computers did not and had to redraw sprites manually to scroll but the games used some very interesting hacks to avoid having to redraw most of the screen and create the illusion of fluid movement by only redrawing parts of it.
Some of the absolute hacks to make games run on the Gameboy were even more impressive.
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.
If you're genuinely curious, The CSS Zen Garden[1] is a great testimony of what people was able to accomplish with the the limitations of CSS2 while keeping support for IE6. That meant: A limited number of fonts, 1 channel transparency, no flexbox or grid for layouts, just floats and positioning. Fun times.
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:
> You can now do everything you could do in Flash, with CSS.
AND JavaScript.
With Flash, you just needed to know Flash. With HTML5, you need to know a whole lot more about DOM manipulation. If you're animating SVGs, that has its own markup and learning curve.
Flash could also do 3D animation, which CSS cannot. You need to know WebGL and a library like three.js for that to be workable.
By far the best WYSIWIG animation tool I've used is Tumult Hype for Mac. It handles the creation of all the JS-based animation triggers through the GUI. I hope there will be a WebGL version of this that is as easy to use.
> Flash could also do 3D animation, which CSS cannot
Saw a few Codepens over the years[0] where people managed to rotate 3D cubes, all done entirely with CSS. Of course if you needed to interact with the cube you would need JS, but 3D can be achieved with CSS alone, it's just a very hacky way of doing it.
That article is about rotating 2-D shapes on the z-axis (3-D plane).
An image of a cube in an HTML document will look like 3D without any transforms applied. However if you try to rotate that image on the Z-axis, it will warp, clearly showing that it is still a 2D object. There are other necessary aspects of 3D such as camera angles and dynamic light and shadows, but that's outside the scope of what you'd expect to be supported in the official CSS spec.
HTML and CSS don't support 3D shape manipulation and motion. WebGL is needed for that.
However, Flash was really easy to get into. You didn't need any programming whatsoever if all you wanted was a vector cartoon. And you did need to copy-paste some ActionScript if you wanted a fancy-looking navigation bar. Current web lacks this ease of authoring, so I wouldn't say "you can now do everything you could do in Flash".
Flash also felt more like a proper application framework. Web still feels like you're working with an extremely advanced word processor.
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.
The first time I've stepped out of the shadows as a lurker just to +1 your comment on "squishy" buttons. I recently saw this technique used on matcha.xyz/blog and I must say I am also a big fan.
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 have always stayed away from scale() whenever avoidable, especially using scale(0) to hide an element caused issues when the element is scaled up again.
Depending on the positioning of the parent and sibling elements, it caused too many reflows and pushed other elements around, too much mental gymnastics for my liking.
It can be useful, just my personal experience.
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.
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.