Skip to main content

The Cascade is a blog about the past, present, and future of CSS.

Howdy—Robin Rendle here.

This blog keeps me in the loop with everything that’s possible with CSS lately but it’s also a reminder to celebrate the people doing the hard work building stuff for the web.

You can subscribe to The Cascade via RSS, shoot me an email if you absolutely must, or follow the feed. This project is directly supported by readers and the membership program.

Right now the newsletter is taking a bit of a break whilst I figure out a healthy publishing cadence, but you can subscribe below:

HTML whitespace is broken

Doug Parker made some interesting notes about the unexpected behavior of whitespace:

Why exactly does HTML work this way? Why did we make this language so complicated?

I think the core problem here is that all whitespace in HTML is ambiguous. Specifically, it is ambiguous with regard to the developer's intent. For any given space, did the developer mean for it to be displayed to the user or did they just want to keep their code under the line length limit? It's impossible for the browser to know.

To address this, the designers of HTML tried to come up with a set of rules which would roughly map the HTML code they wanted to write to the rendered output they wanted to create. So you, as a developer, have a UI in your head and write out the HTML to display it, and usually the whitespace "just works".

The unpredictability of whitespace causes all sorts of problems as Doug notes: code formatting bugs, accidental line breaks, etc. and there’s been so, so many times that I’ve had to fight whitespace that often I’ve just hacked things together until it works right or let it act out and be wrong and weird.

Doug mentions that although we can’t easily change this behavior of HTML without breaking changes, he recommends adding a new entity to help: &ncsp;.

Chasing color

I love this post Adam Stoddard on building a color and theming system for his website because it outlines all the hidden and oft-ignored complexities behind great UI engineering. Adam writes:

What does an ideal CSS color system look like? My answer to this question has evolved along the way, but here’s what I think, today:

  • Composable, cascading themes - You should be able to set different themes at the page-level, section-level, and component-level, and have them cascade down until a different theme is applied.
  • Light & dark mode for all themes - Color themes shouldn’t be in addition to light and dark mode, every theme includes light and dark mode support.
  • Expressive - It should be easy to change opacity, use tints and shades, etc. within the context of your system. No having to go off system just because you need to add transparency.
  • Micromanagement-free - You should never even have to think about working with specific hues at the component level. In other words, adding a new theme shouldn’t mean touching every component.
  • Small set of properties - You should be able to worth with a small set of properties that you can further modify vs. maintaining an extensive list of semantic colors. Easier to work with, and easier to make new themes.
  • Good DX - It should feel good to work with. Flexible, straightforward, reads intuitively, forgiving, consistent, etc.

Adam then walks step by step how we could go about doing that whilst listing the cons to his approach. One thing I really like about this system is how Adam uses the new light-dark() function that I’d totally forgotten about. Super neat stuff.

The animation-composition property

How have I never heard of the animation-composition property before? I just spotted it over on Manuel Matuzović’s blog:

CSS animations can be composited in three ways: replace, add, and accumulate. The animation-composition property allows you to switch between them.

Huh! So you can effectively add, replace, or combine animations together which is something I’ve never thought about before! I had never even thought much about the default behavior too, which replaces an animation on an element, so that in the CSS below the .element will only move 100px...

.element {
  animation: move 2s infinite;
  transform: translateX(10px);
}

@keyframes move {
  to {
    transform: translateX(100px);
  }
}

But what if you wanted these properties to stack, so that you have 100 + 10 here? That’s what animation-composition is for and you can use it like this:

.element {
  animation: move 2s infinite;
  transform: translateX(10px);
  animation-composition: add;
}

@keyframes move {
	to {
		transform: translateX(100px);
	}
}

Huh! Very neat indeed!

The funny thing is that when I saw this property this morning my first thought was: why on earth do we need this? I couldn’t imagine scenarios where this would help me out of tricky problems or help me with animation work (which, admittedly, is very rare for me). And then later in the afternoon I was working with an engineer and realized that we could use this animation-composition stuff without writing a bunch of complicated JavaScript!

Oh and make sure to check out Bramus’ post combining multiple animation effects, too.

Wakamai Fondue

This is your daily reminder that Wakamai Fondue is an invaluable resource when dealing with font files. A lot of the time I’ll buy a font and the PDF specimen won’t tell me how to use a feature with CSS! It’s annoying!

Thankfully the open beta has a host of improvements when it comes to variable fonts too, so first you upload your font and then tweak the optical size, weight, width, or turn on stylistic sets, fractions, and countless other OpenType goodies. It’ll then spit out the CSS that you need, like this:

.element {
  font-feature-settings: "c2sc" 1, "dnom" 1, "frac" 1, "lnum" 1, "smcp" 1, "ss01" 1, "ss03" 1, "ss05" 1;
  font-variation-settings: "opsz" 48, "wght" 300, "wdth" 100, "ital" 1;
}

Reckoning

Alex Russell has written a fantastic series of posts on the “JavaScript-industrial-complex” where he explores how the current state of web performance has become unacceptable and how dire the situation has become:

We are not getting better UX for the escalating capital and operational costs. Instead, the results are getting worse for folks on the margins. JavaScript-driven frontend complexity hasn't just driven out the CSS and semantic-markup experts that used to deliver usable experiences for everyone, it is now a magnifier of inequality.

Each post is endlessly quote-worthy because so much of it matches my experience working on big, slow web apps which, for the most part, have ignored the lessons of progressive enhancement. Why are websites like this? Why are they embarrassing?

Well, Alex makes this great point:

Unacceptable performance is the consequence of a chain of failures to put the user first. Breaking the chain usually requires just one insistent advocate.

He then takes this one step further and argues that the biggest threat to the web is the JavaScript-ification of it; bloated, slow websites make an argument against the web ‘platform’ as a whole and might even threaten its future existence. Why not download an app if the website is obviously going to suck?

And so, to save the web, we must first care for the user—and then make our websites fast as hell.

How to animate around a circle

The other day I wanted to make a CSS animation where an object would rotate around a circle so this was the first thing I tried:

@keyframes circle {
  0%{
    transform: rotate(0deg);
  } 100% {
    transform: rotate(360deg);
  }
}

See the Pen Untitled by Robin Rendle (@robinrendle) on CodePen.

Gah! That’s not the right kind of rotation I wanted.

What I really needed was for the whole object to be locked in place and rotate around the center. So I tried again, but this time I added a translate in there:

@keyframes circle {
  0%{
    transform: rotate(0deg) translate(-10px);
  }
  100%{
    transform: rotate(360deg) translate(-10px);
  }
}

See the Pen Rotate Circle 1 by Robin Rendle (@robinrendle) on CodePen.

Okay, that’s got the position I want where the image rotates around a center – but how do I prevent that rotation of the image itself? WELL, I found kirupa’s post about animating items around a point but all those items show the same side to the center as they rotate. So sadly that didn’t help me.

After fiddling with things and playing around, and I cannot tell you how I managed to get here dear reader, but this CSS eventually worked for me:

@keyframes circle {
  0%{
    transform: rotate(0deg) translate(-10px) rotate(0deg);
  }
  100%{
    transform: rotate(360deg) translate(-10px) rotate(-360deg);
  }
}

See the Pen Rotate Circle 2 by Robin Rendle (@robinrendle) on CodePen.

That’s the precise effect I was lookin’ for!

Framer Fetch

This doesn’t have much to do with CSS, but this new feature by Framer called Fetch caught my eye:

The reason why I mention this is because it shows a snapshot of what the future of web design tools might be: they’re not just going to allow you to draw pixels on a canvas, but allow you to build real, interactive software that pings a database.

That’s exciting to me! As a designer by day, I want to make better prototypes of my designs and using real data helps sell my ideas. But it also makes me a little fearful for the future of front-end development? I would see something like this as a prototyping tool, ready to give to a talented UI engineer to build properly once I’m finished with it, but I fear that folks will see this and think of ditching front-end developers altogether.

CSS Grid Areas

After all these years of using CSS Grid and I still feel like I haven’t grokked everything that it’s capable of. Ahmad Shadeed’s latest interactive tutorial is a great reminder of that where he’s written about named grid areas and explains the following bit of CSS:

.layout {
  grid-template-columns:  [full-start] 1fr
                          [content-start] 2fr
                          [content-end] 1fr [full-end];
}

So what Ahmad has done here is defined and named specific areas of a grid and then he can use them elsewhere in his CSS like this:

.layout-item {
  grid-column: content-start / content-end;
}

Smart stuff.

:nth-child(of)

I’m not sure how I fell of the bandwagon of Manuel Matuzović’s excellent 100 days of CSS...

It’s time to get me up to speed with modern CSS. There’s so much new in CSS that I know too little about. To change that I’ve started #100DaysOfMoreOrLessModernCSS. Why more or less modern CSS? Because some topics will be about cutting-edge features, while other stuff has been around for quite a while already, but I just have little to no experience with it.

That’s from the latest post all about this syntax I’d never seen before:

li:nth-child(even of :not([hidden])) {
  background-color: aqua;
}

The idea is to filter all of the even list elements that aren’t hidden. That is extremely useful and good to know!

My favorite line of CSS

I think my favorite line of CSS has finally been usurped! For maybe a decade my favorite line was this bad boy:

.element {
	display: grid;
	place-items: center;
}

Pure, simple, perfect. Throw some viewport units in on top and you now have Megazord-like super powers to take control of the browser canvas like you never could before.

Now though, my favorite line is this:

@view-transition {
	navigation: auto;
}

As Dave Rupert wrote a while back, this is the easiest way to add view transitions to your website today. And I’ve already added them here and on my blog whilst I figure out how exactly pages should animate in and out without making everyone sick of it.

Honestly, if this was the new default animation between pages on the internet then I’d be chuffed to bits. It feels a bit more app-like, a bit more polished and less janky then the clunky page switching of the past.

But but but!

Eric Portis warns us that this is all more complicated than it seems and when we add view transitions we need to test the heck out of them because they break incremental loading:

I worry that giving developers tools to explicitly block render – with or without View Transitions – is going to make experiencing the web on slow connections and cheap devices much worse.

[...] We need tuned timeouts that ensure that the long tail of slow devices/connections don’t wait for View Transitions if they would excessively delay first paint.

So: I am very excited about my favorite new line of CSS but we have to tread lightly with this stuff because it could end up hurting folks more than it helps.

Motion blur

Oooooh here’s something I’ve never thought about when it comes to CSS: motion blur! Adam Argyle wrote this back in 2019 (!) but it still feels new and exciting to me:

Professional polish of motion graphics often includes the application of motion blur. In most cases, it's a boolean toggled at the layer level, that then tells the engine to set a blur amount based on the speed of the pixels. This effect makes animations much closer to real life, among other nice benefits. CSS currently is incapable of such an effect. Instead, a strobing, ghosted type effect is often what we get instead.

I like this proposal, too:

.animated-layer {
  animation: rotate .5s linear infinite;
  motion-rendering: blur;
  motion-shutter-angle: 180deg;
}

@keyframes rotate {
  to {
    transform: rotate(1turn);
  }
}

Also, reading the comments on this thread is fun and reveals just how complex the standards process is for adding anything new to CSS.

Inline conditionals in CSS, now?

This is a great post by Lea Verou all about conditional statements in CSS:

A couple days ago, I posted about the recent CSS WG resolution to add an if() function to CSS. Great as it may be, this is still a long way off, two years if everything goes super smoothly, more if not. So what can you do when you need conditionals right now?

You may be pleased to find that you’re not completely out of luck. There is a series of brilliant, horrible hacks that enable you to expose the kinds of higher level custom properties that conditionals typically enable.

One technique that hurts my brain to think about is what Jane Ori called “type grinding” a few years ago. The idea is that you daisy-chain multiple @property declarations to change the value of a CSS variable as it passes through them. Which makes for a wild, mind-bending read.

Javascript free navigation

Thanks to Andy Bell’s ever-so-good newsletter, The Index, I found myself ooo-ing and aaa-ing at Michelle Barker’s excellent post from back in May about creating a JavaScript-free menu with the latest bells and whistles like anchor-positioning and the Popover API:

Anchor positioning in CSS enables us to position an element relative to an anchor element anywhere on the page. Prior to this we could only position an element relative to its closest positioned ancestor, which sometimes meant doing some HTML and CSS gymnastics or, more often than not, resorting to Javascript for positioning elements like tooltips or nested submenus.

There’s a lot of good examples in that post that are worth checking out but one thing that stuck out to me was the <menu> HTML element which we can use like this for a series of interactive actions:

<menu>
  <li><button>Copy</button></li>
  <li><button>Cut</button></li>
  <li><button>Paste</button></li>
</menu>

...how have I never used this before!?

Learn Grid Now, Container Queries Can Wait

Miriam Suzanne:

There’s no rush to rip out all your media queries, and replace them with containers. You’ll be fine waiting for widely available support and your next scheduled re-factor.

But if you’re still avoiding grid – whatever your reasons – you are, in fact, missing out. CSS grid is one of the best features in CSS, and one of the biggest time-savers on every site we build.

One part of Grid that I’ve been ignoring for too long is the whole template areas syntax...

.grid {
  display: grid;
  grid-template-areas:
    "head head"
    "nav  main"
    ".  foot";
}

.grid header {
  grid-area: head;
}

/* etc. etc. */

For some reason it doesn’t feel grid-y enough for me but I should just sit down and try to get used to it. Even looking at it now I’m slowly realizing that it’s real nice that you can use . to denote an empty column which makes things quite a bit easier. Oh and this reminds me, the other day I spotted this CSS Grid Template Builder by Anthony Dugois and it’s pretty handy!