CSS snippets
I’ve been thinking about the kind of CSS I write by default when I start a new project.
Some of it is habitual. I now use logical properties automatically. It took me a while to rewire my brain, but now seeing left
or top
in a style sheet looks wrong to me.
When I mentioned this recently, I had some pushback from people wondering why you’d bother using logical properites if you never planned to translate the website into a language with a different writing system. I pointed out that even if you don’t plan to translate a web page, a user may still choose to. Using logical properties helps them. From that perspective, it’s kind of like using user preference queries.
That’s something else I use by default now. If I’ve got any animations or transitions in my CSS, I wrap them in prefers-reduced-motion: no-preference
query.
For instance, I’m a huge fan of view transitions and I enable them by default on every new project, but I do it like this:
@media (prefers-reduced-motion: no-preference) {
@view-transition {
navigation: auto;
}
}
I’ll usually have a prefers-color-scheme
query for dark mode too. This is often quite straightforward if I’m using custom properties for colours, something else I’m doing habitually. And now I’m starting to use OKLCH for those colours, even if they start as hexadecimal values.
Custom properties are something else I reach for a lot, though I try to avoid premature optimisation. Generally I wait until I spot a value I’m using more than two or three times in a stylesheet; then I convert it to a custom property.
I make full use of clamp()
for text sizing. Sometimes I’ll just set a fluid width on the html
element and then size everything else with em
s or rem
s. More often, I’ll use Utopia to flow between different type scales.
Okay, those are all features of CSS—logical properties, preference queries, view transitions, custom properties, fluid type—but what about actual snippets of CSS that I re-use from project to project?
I’m not talking about a CSS reset, which usually involves zeroing out the initial values provided by the browser. I’m talking about tiny little enhancements just one level up from those user-agent styles.
Here’s one I picked up from Eric that I apply to the figcaption
element:
figcaption {
max-inline-size: max-content;
margin-inline: auto;
}
That will centre-align the text until it wraps onto more than one line, at which point it’s no longer centred. Neat!
Here’s another one I start with on every project:
a:focus-visible {
outline-offset: 0.25em;
outline-width: 0.25em;
outline-color: currentColor;
}
That puts a nice chunky focus ring on links when they’re tabbed to. Personally, I like having the focus ring relative to the font size of the link but I know other people prefer to use a pixel size. You do you. Using the currentColor
of the focused is usually a good starting point, thought I might end up over-riding this with a different hightlight colour.
Then there’s typography. Rich has a veritable cornucopia of starting styles you can use to improve typography in CSS.
Something I’m reaching for now is the text-wrap
property with its new values of pretty
and balance
:
ul,ol,dl,dt,dd,p,figure,blockquote {
hanging-punctuation: first last;
text-wrap: pretty;
}
And maybe this for headings, if they’re being centred:
h1,h2,h3,h4,h5,h6 {
text-align: center;
text-wrap: balance;
}
All of these little snippets should be easily over-writable so I tend to wrap them in a :where()
selector to reduce their specificity:
:where(figcaption) {
max-inline-size: max-content;
margin-inline: auto;
}
:where(a:focus-visible) {
outline-offset: 0.25em;
outline-width: 0.25em;
outline-color: currentColor;
}
:where(ul,ol,dl,dt,dd,p,figure,blockquote) {
hanging-punctuation: first last;
text-wrap: pretty;
}
But if I really want them to be easily over-writable, then the galaxy-brain move would be to put them in their own cascade layer. That’s what Manu does with his CSS boilerplate:
@layer core, third-party, components, utility;
Then I could put those snippets in the core
layer, making sure they could be overwritten by the CSS in any of the other layers:
@layer core {
figcaption {
max-inline-size: max-content;
margin-inline: auto;
}
a:focus-visible {
outline-offset: 0.25em;
outline-width: 0.25em;
outline-color: currentColor;
}
ul,ol,dl,dt,dd,p,figure,blockquote {
hanging-punctuation: first last;
text-wrap: pretty;
}
}
For now I’m just using :where()
but I think I should start using cascade layers.
I also want to start training myself to use the lh
value (line-height) for block spacing.
And although I’m using the :has()
selector, I don’t think I’ve yet trained my brain to reach for it by default.
CSS has sooooo much to offer today—I want to make sure I’m taking full advantage of it.