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.
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.
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;
}
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.
Here’s a fantastic trick with background-attachment: fixed
from Kevin Powell:
Huh! Also, doing a quick search for other cool things you can do with this trick, I found that Geoff already made a collection of use cases for fixed backgrounds in CSS years ago that’s worth checking out, too.
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!
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.
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.
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!
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.
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.
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.
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!?
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;
}
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!
CSS Grid has made me lazy. Whenever I start a new project I tend to pick a 12 column grid and move on to other things...
.grid {
grid-template-columns: repeat(12, 1fr);
}
...it’s almost too easy! This is probably also out of laziness in the design, too. I’d often pickup the Bootstrap grid and after years of use I began to see every page built out of 12 columns. So layouts, and the grid systems they’re built out of, felt like a solved problem to me.
But I got into a layout pickle the other day because of this laziness: I realized that my layout looked so weird and wonky here on The Cascade because I was using my trusty 12 column layout without thinking about it. I’d then set every element on the page to fit within those arbitrary constraints:
.main {
grid-column: 5/13;
}
.sidebar {
grid-column: 1/5;
}
The problem here was the sidebar would stretch too far at larger screen sizes and felt visually gross. So I did the unthinkable and tweaked the grid to fit the content instead:
.grid {
grid-template-columns: repeat(4, minmax(auto, 80px)) repeat(7, auto);
}
Translation: “make 4 columns with a max-width of 80px each, and then 7 columns that take up the space left over.” Reading CSS like this always takes an extra second for me to parse and walkthrough step by step but effectively all we’re doing here is telling the first 4 columns to be a different size than the remaining columns.
Gasp! An asymmetric grid! The horror!
Anyway, CSS grid is just a tool and it doesn’t have to be perfect or simple or make everything line up in equal measure. But I also realized here that the grid should always be subservient to the content.
Or: content first, grid last.