“Ask not just: How well does it work?
But also: How well does it fail?
What happens when something goes wrong?”
—Jeremy Keith
The
2022 Web Almanac
has been out for a while,
and (as always)
it’s an interesting read.
There are more than 20 chapters this year,
and I haven’t read them all.
But I did enjoy the chapters on
CSS
(by Rachel Andrew)
and webfonts
(by Bram Stein).
Both authors note a similar trend –
many usage patterns
that refuse to change from year to year
can be explained by popular tools.
I’ve noticed that same effect elsewhere,
and I want to dig into it a bit –
the various ways our tooling
can change (and limit)
the web platform features we use.
According to the Almanac data,
the most common color formats on the web
are HEX (#C71585),
short-form HEX (#c18),
and then old-school
rgba(199, 21, 133, 0.8).
But why are we still using
the oldest and least legible
color formats,
when better formats are well-supported?
HSL is more human-readable than HEX,
and the rgb() function
now supports alpha transparency
without switching to rgba().
Alternately, if we like HEX so much,
why don’t we use the alpha-HEX syntax
(#C7158599)
that’s been supported for several years.
Why aren’t these options gaining popularity?
It’s hard to say for sure,
but I have a multi-part guess.
First, colors are design tokens,
and often get set as custom properties
or build-tool variables
at the start of a project.
Once the tokens are established,
we don’t spend much time looking at
the actual color syntax underneath.
I don’t ever interact directly
with the HEX code #E60073 –
I can just reference
var(--brand-pink).
So we focus our attention on the naming conventions
rather than the underlying color syntax,
which is hidden from view.
I think there’s also a tooling component here.
Many graphic design tools are a step removed
from the web platform.
While some do try to export HTML/CSS,
only a few consider that
the core goal of the tool.
Even then, there’s been a long-term disconnect
between a web that’s responsive,
and our almost completely static design tools.
A few tools have started to provide
flexbox-like ‘responsive’ layouts,
but I haven’t seen anything CSS-grid-like.
Most don’t even have
basic support for relative or fluid units.
Rachel notes in the Almanac
that most lengths on the web
are defined in px.
Is that because authors intentionally avoid em/rem,
or because the mockups that we receive from designers
are all limited to px by our design tools?
The least responsive part
of Responsive Web Design
is the design tools.
This needs to change.
When it comes to color spaces/gamuts,
design tools vary in support.
Looking at some of the big players:
Adobe XD
supports HEX, RGB, and HSB.
Illustrator adds CMYK and a grayscale option,
while Photoshop also supports extended gamuts
such as Display P3,
and perceptually-uniform LAB.
Figma
(now also owned by Adobe)
provides HEX, RGB,
‘CSS’ (which is rgba()),
HSL, and HSB.
Sketch
shows HSB, HEX, and RGB(a).
I don’t know of any popular design tools
that provide LCH,
or the newer okLAB/okLCH variants,
let alone relative colors
defined as a function of mixing or adjusting
other underlying colors.
And when it comes to copying our colors
out of a design tool,
the options are generally 6-digit HEX,
or copying individual channel values,
one at a time.
Either way,
converting our colors
into a more human-friendly syntax
would often be an extra step,
and may not be worth the effort.
Since all legacy colors on the web
rely on a single color model (RGB)
and gamut (sRGB),
there has been little meaningful difference
between formats (until now).
Once we used a graphic interface
to pick the color we want,
it maybe didn’t matter
what format we copy-pasted into
a variable somewhere.
But what’s the designer path
towards using new, extended color spaces in CSS?
Can they ever gain traction on the web
without first finding support in our design tools?
I’m not sure.
Sass, for example,
relies on the same
interchangeability of legacy web formats.
No matter what syntax an author chooses,
Sass will store the value as RGB,
and then allow manipulation
in any other CSS format.
But at the end of the day,
CSS output is always generated
in whatever format has the widest browser support.
It doesn’t matter to Sass
what syntax authors use
for their input value,
the output value is always
either HEX or a color name when opaque,
with rgba() for handling transparency.
Very few people need that level
of legacy browser support,
but it’s not hurting anything either.
In this case,
the Almanac may give us misleading info
about what syntax authors prefer.
For all we know,
authors might be working primarily in HSL,
and we wouldn’t see that
in the production code at all.
In fact,
one of the most popular complaints
on the Sass issue tracker is
a request for HSL output.
But this is a distinction
with very little at stake.
So long as authors can use their favorite format –
and the output really does
provide the same meaning as the input –
it’s not a barrier for authors
using the latest color formats.
We’re just making that harder to see.
In Sass,
we have a strict policy
that valid CSS is always valid Sass.
If authors use syntax that we don’t recognize,
we pass that along to CSS.
We can check for obvious parsing errors,
but only the browser can determine
if it’s a supported feature.
While we provide extra Sass support
for colors that we understand,
authors can use new CSS color formats in Sass
without us releasing any new features.
Sass may not understand those colors for a time,
but it will leave them untouched in the CSS output.
Similarly,
Sass hasn’t added support
for either @layer or @container –
and there may not be any reason to.
I’m already using both in my Sass,
without any issue.
There have been unfortunate exceptions on occasion
(see min() and max() for example),
but we’ve worked very hard to remove those limitations
when they crop up.
The tool should never stand between
authors and the underlying language.
Last month,
I spoke about @layer for
An Event Apart Denver.
During the Q&A session after my talk,
someone asked,
“How can I use this with CSS-in-JS tools?”
And the truth is…
I don’t know.
It depends entirely on the tool.
Single-file components in tools like Svelte & Vue
are technicallyCSS-in-JS,
but allow writing arbitrary/plain CSS.
I would expect (hope?) that
@layer should just work in that context
(similar to using Sass).
But many CSS-in-JS tools
and utility frameworks
are more invasive –
replacing some or most CSS with a proprietary syntax.
They don’t provide additions to the language,
but a whole new language
that stands directly between us
and the basic CSS functionality we need.
There’s no option to write CSS directly,
we have to rely on the tool to do it for us.
If the tool can’t do something,
neither can the authors using it.
All we can do is wait.
I even ran into this issue
by simply hosting my personal site
on Netlify,
which provides minification
for deployed assets like CSS.
That seems like a great feature!
But the specific CSS minifier that they use
is somewhat overeager,
and began stripping out all my new
@layer rules.
I had to turn off the minification step
in order to publish my entirely-valid CSS.
That shouldn’t be the case.
Minifiers shouldn’t need to understand
all the new features that land in CSS.
This is similar to the issue with
removing units from zero,
or Harry Roberts’ recent warnings around
Critical CSS.
In a language like CSS –
where order is meaningful,
and duplicate properties are a useful feature –
it’s risky for automated build tools
to try and be clever about minification.
I don’t know that a CSS minifier
should do much more than white-space management.
In regard to web fonts,
Bram points out
that authors are not taking full advantage
of variable fonts –
we’re mostly changing the font weights,
and selecting from standard values.
As someone who has spent hours
searching through lists of variable fonts,
that doesn’t surprise me much.
Most variable fonts are either experimental display fonts
without a lot of practical use,
or they only provide a single weight axis.
While I love having all my weights in a single file
and smoothly transitioning from one weight to another,
specialty weights are not a high priority for me.
I’ll start using more powerful font variables
once there are more fonts available
with more interesting variables to manipulate.
Most of us are also using
the over-complicated font-feature-settings property,
instead of the simpler font-variant.
I’ve been doing that on my site as well!
Why did I think that was the best approach?
Likely because that’s the generated output
recommended by
Wakamai Fondue –
a popular tool for inspecting font capabilities.
It’s a great tool,
filling a much-needed gap,
but I wonder how the usage stats would change
if they updated their output CSS?
Maybe even more common,
much of the web is built using CSS libraries
like Bootstrap,
or third-party themes
provided by a site-builder or CMS.
The influence of both
WordPress and Bootstrap is clear
throughout the Almanac data.
When Rachel notes the popularity of
flexbox (very popular) vs grid (not so much),
I wonder how much of that
can be traced back to
Bootstrap ‘grids’
being built in flexbox.
I don’t think that’s the only factor.
It’s possible authors have settled on flexbox as good-enough,
and they don’t think it’s worth their time
learning another technique.
I can understand that,
but it’s unfortunate.
I think people are missing out
on one of the coolest features
added to CSSever.
In context,
Jeremy is not just referring to
the web languages themselves –
JS isn’t necessarily changing faster than CSS –
but also the ecosystems of these languages.
The closer we get to the core functionality of the web,
the slower each language/ecosystem is likely to change.
Even within a given language,
we expect our tools and conventions (fashion)
to move faster than the languages themselves.
But that can only happen
if the tools are designed to
sit on top of their underlying languages.
Once the tools stand between us and the language,
we become entirely reliant on tool-builders
to determine what features are available.
When our primary tools
intervene so strongly
between us and our ‘materials’ –
the core web languages –
we can accidentally flip the pace layers of the web
on their head.
Suddenly CSS is able to move faster than the ecosystem,
and we’re stuck waiting on our tools to catch up
with well-supported platform features.
I am asked quite often
what I think about CSS-in-JS
or utility-first frameworks,
or even CSS libraries & conventions
more generally.
And I try to stay out of any spicy flame wars,
or gate-keeping nonsense.
For myself?
I don’t find many of these tools useful.
They don’t solve a problem that I have.
But different projects and different teams
have different needs,
and might find different tools useful.
There’s no single ‘correct’ approach
for writing all CSS everywhere.
As long as it results in an
accessible, resilient,
and performant experience for users:
use whatever tools work best for you.
(Anyone marketing their product
as The Only Solution™️ to some
Essential Problem with CSS™️
is selling you a religion,
not a tool.)
It’s not my job to judge
what tools are useful for other web developers.
But it is my job to
help people think about the CSS choices they make.
So in that spirit, please consider:
⚠️🚨⚠️
When tools intervene
between you and your access to the web platform,
proceed with caution.
Ask not only: How well does it work?
But also: How well does it fail?
Not only: What features do they provide?
But also: What features do they prevent?
⚠️🚨⚠️
@matthiasott@mia I wonder if the tooling has followed the front-end community, which has largely undervalued CSS for a long time now. And now that’s come home to roost.
@mia This is so down my alley. There are growing gaps anywhere atm, and one of the greatest “great divides” is the one between what is possible today with the material(s) of the Web and what designers know about it and are able to create in design tools.
@matthiasott I also get the problem there, it’s not easy to solve. How do you provide the full power of CSS in a graphic interface? Reproducing the language as a series of form fields is not exactly elegant.
On the code tooling side, I think people also leaned into…
“Suddenly CSS is able to move faster than the ecosystem, and we’re stuck waiting on our tools to catch up with well-supported platform features. That’s not how a healthy ecosystem should behave.” Fully agree!
Back in the day, I’d sometimes use a hack when I had to make IE6 work. I’ve always insisted that any hack has to be valid CSS. It shouldn’t be our fault when a site breaks because we ignored non-conforming code. Apparently, it’s okay for tools to mess it up…
That’s when I broke a sweat, waiting for Mia to start naming names. The part about design tools being a step removed from the web also rang true with a heavy heart. Even popular tools designed explicitly for export on the web are priming to hold it back.
Yeah, the first draft ended with “In summary: everything is Jon’s fault. Blame Jon.” – but the editors thought that was a bit much (and not really supported by the data). 😅
For many years, it has been ‘best practice’ to use relative units (especially em and rem) for sizing text. That’s great! But after playing around with my user preferences, I think we can improve on the common approaches.
It is frustrating to track down why an anchor isn’t being found. I’ve found a simple way that should work in most cases. If that doesn’t work, step through the checklist, and then dive in to get a better understanding of how Anchor Positioning works.