
In Defense of Utility-First CSS (2018) - jackkinsella
https://frontstuff.io/in-defense-of-utility-first-css
======
ravenstine
To each their own, but I personally learned to hate this approach. In my
experience, it leads to a CSS spaghetti full of overrides and `!important`
just to get all the utility classes to play nicely across a site. And of
course the markup becomes less readable.

I prefer to just write classes for specific components with some modifier
classes to toggle variations. People resist this because they've been taught
to avoid repetition, but I've found that repetition is a good trade-off for
things just making more sense because _it 's really not that hard_ to go in
and change the same pattern repeated among CSS selectors if there's a site-
wide design change. If you really hate repetition, you can still use CSS
variables and SCSS mixins. But the end product of the CSS definitions should
be styles that are easy to use, don't tangle with each other, and make it
clear what an element represents.

What I describe becomes even more practical if you separate your CSS concerns
into concepts like "layout" and "component" or "design". That way the styles
that handle your page layout and responsiveness don't get tangled with the
styles that handle the appearance of elements.

Here's a blog post I wrote that goes into more detail about my approach to
CSS: [https://tenbit.co/blog/my-approach-to-writing-
maintainable-c...](https://tenbit.co/blog/my-approach-to-writing-maintainable-
css/)

 _(I only recently discovered that the page heading is kinda broken on mobile.
Sorry.)_

~~~
hinkley
We have bad terminology and insufficient training I think. We are deep into
metric dysfunction now thinking the repetition of very small blocks of text is
wasteful, even shameful.

That’s not the duplication that matters. The duplication that matters is the
effort. Having to do the same action over and over, and ensuring the same
result occurs. That’s expensive. That’s draining.

Trying to deduplicate code that is structurally similar but has different aims
just creates a problem later on.

~~~
dwaltrip
> Trying to deduplicate code that is structurally similar but has different
> aims just creates a problem later on.

This is one of the most important lessons I've learned in software.
Abstractions work well when the snippets in question have similar, coupled
requirements. The proposed abstraction must target the shared requirements, or
it will soon cause more problems than it solves as the snippets diverge due to
their different purposes. Structural similarity alone provides very limited
opportunity for a robust abstraction.

A rough heuristic that may indicate one of these problematic abstractions is
the number of special cases and if-elses that are continually being added to
make it work.

------
donatj
They makes a very poor case IMHO, and come off as just preaching to the choir.

> Make no mistake: just because style composition is performed in the HTML
> document doesn’t mean it’s done in HTML.

That is 100% what that means. Sure, you _could_ make .font-italic do anything,
yet if it turns everything bold or anything other than italic it’s a horrible
sin.

Make no mistake, you are editing your HTML to adjust styling. It’s “done in
html”.

Truly semantic CSS has been dead for around a decade, killed by the likes of
Bootstrap. God I miss it. I miss the goal of just cleanly naming things what
they are, not how they look. Taking pride in the quality of the HTML, versus
today’s rush to get an MVP out the door as quick as possible.

~~~
klum
> God I miss it. I miss the goal of just cleanly naming things what they are,
> not how they look.

I think utility-first CSS has its benefits as well as it's drawbacks, but just
regarding the statement above: wouldn't you say that when naming things for
the purpose of targeting them with styling, what they look like is indeed what
they are?

As in, referring to, for example, ".comment" and ".testimonial" in your CSS,
when those classes have been added purely for the purpose of styling the
elements as what is commonly called a media component, could be considered
less semantic than just naming them according to how they look -- as that's
the reason for naming them in this case?

(I think these are two different ways of looking at the issue, none of which
is clearly the right or wrong one.)

~~~
thinkloop
> wouldn't you say that when naming things for the purpose of targeting them
> with styling, what they look like is indeed what they are?

What do you mean? A "comment" is likely to stay a "comment" forever, whereas
its bold'ness or italic'ness can/will likely change relatively often.

~~~
klum
Well, yes. So, in the hypothetical situation where classes are added just for
styling, is it a given that the correct way to name it is a way that stays the
same when the styling changes?

~~~
thinkloop
> in the hypothetical situation where classes are added just for styling

OK, a style-based class naming system

> is it a given that the correct way to name it is a way that stays the same
> when the styling changes

Not with a style-based naming system, in that case it's ok for the class name
to change, and you can expect it to change often, which a lot of people argue
is ok.

But like @welly said, herein lies the problem, or preference. The argument is
exactly about whether you should name things in unchanging "decoupled" ways,
or whether that doesn't work out in practice and it's simpler to just have
utility styles.

------
mikl
Utility-classes like `font-16 font-bold font-purple` are essentially just
shorthand for writing inline CSS. You are defining the styling in HTML, with a
utility CSS file as go-between, true, but if you use Tachyons or Tailwind the
way they’re supposed to be used, the way to change the look of an element is
to go edit the HTML.

For component libraries, that makes a lot of sense. You re-use snippets of
HTML that is styled a certain way. No need to set up another re-use layer
using CSS.

I expect the next level of utility-first CSS will do away with the CSS file
altogether, and start baking the resulting styles directly into the HTML, so
<div tx(['font-bold', 'font-16', 'font-purple'])> would be transformed by
whatever you use for HTML rendering into <div style="font-weight: bold;font-
size: 16px;color: purple">. That would complete the circle and cut away a lot
of complexity.

~~~
lfischer
What you describe sounds like the way some use CSS-in-JS frameworks as emotion
or Styled Components.

~~~
mikl
Yeah, they’re currently just one step away, generating class names on the fly
and attaching those classes to elements.

------
shubhamjain
If you're not sold on Utility-first CSS, your gut reaction would be, how's it
different from inline styles? The author does a great job at listing out the
differences, but I think that kinda misses the point.

If you've to accept Utility-first CSS, you should unlearn the fact that there
is something inherently wrong with inline-styles. Often, they are much cleaner
solutions than creating an entirely different class that won't be used more
than once. Utility-First CSS only makes it easier to use inline styles (by
reducing verbosity) and provides a standard set of classes so you don't end up
creating 100 variants of margins.

I have found it hard to convince folks this is indeed a good approach because
inline styles have acquired a reputation of being a disgusting hack. A while
ago, my outlook was not very different. But then, I started seeing how often I
was writing the same styling rules again and again. Our 1MB stylesheet was
nothing more than a repetition of a few basic rules. Utility-first CSS builds
on that idea and to me, it feels natural.

~~~
al2o3cr

        Utility-First CSS only makes it easier to use inline styles 
        (by reducing verbosity) and provides a standard set of 
        classes so you don't end up creating 100 variants of margins.
    

If your "standard set" has 3 varieties each for top/bottom/left/right margin,
you've already got 81 combinations of margins available at each element.

~~~
dceddia
I was just today watching some of the videos Adam Wathan put together for
Tailwind [0] and this one on "Optimizing for Production"[1] is especially
relevant to your comment.

You can introduce a build step (in his example, PurgeCSS) to filter down to
only the styles that you actually use. So during development you'd have
thousands of available classes, but in practice you only use a handful, and
that final CSS file can be significantly reduced.

I'm not (yet?) fully on board the utility-first bandwagon and I have yet to
give it a solid try, but I was excited by the idea that it should be pretty
optimizable.

[0] [https://tailwindcss.com/course/](https://tailwindcss.com/course/)

[1] [https://tailwindcss.com/course/optimizing-for-
production](https://tailwindcss.com/course/optimizing-for-production)

------
lfischer
Lately I’ve been intrigued by [https://every-layout.dev/](https://every-
layout.dev/) and so-called ‘intrinsic’ CSS approaches. It’s like having
utilities for whole layout chunks, instead of single properties. I would
describe it as trying to extract whole atomic layouts like ‘sidebar’, with CSS
rules that make the objects behave ‘well’ no-matter what the surroundings are.
In comparison, semantic CSS can be too tied to single page elements
(main__header) while utility-first in a sense is not ambitious enough (because
it limits atomicity to single properties).

------
btbuildem
I've switched to this approach a while ago, and haven't looked back since. It
makes everything so much simpler, hands down.

I have utility classes, grouped semantically into separate css files. I've
built up a library of components that I use across my projects (so eg. if I
need to change a button, I just change it on the component server).
Encapsulating style, function and semantics in separate layers has really
increased my efficiency as a developer.

Interesting challenges arise when collaborating with UX / UI designers. Quite
a few of their tools (XD, Figma, etc) can output ready-made CSS blobs for
front-end dev copypasta, but it's the old-school semantic CSS.

What I have found reassuring though is that in general, designers eventually
come up with UI kits, and there are certain stylistic consistencies inherent
to those. The kits usually translate very well to a functional CSS
implementation because of that.

------
saagarjha
I’m not familiar with Utility-First CSS: is it where you add class=“color-blue
underline font-big” to your links instead of class=“header-link” and add the
CSS to do the styling to the class? If so, I’m not sure I can shake the
“yuckiness” I feel by choosing to not annotate an element with its semantic
meaning. It seems awfully likely that you’d get the same issues you’d see with
styling divs instead of using actual HTML elements…

------
mynegation
I disagree with the author but I appreciated very thorough explanation of
various CSS structuring approaches - it was very helpful for me. Disclaimer:
my knowledge of CSS is 2 out of 10 at best, but my personal preference is the
semantic way: use header, footer, article tags and use either div’s with
semantically name classes (like ‘card’) or React components or web components.
If CSS is more complicated as a result of that - I don’t care, there are ways
to deal with that (extend, variables, preprocesssors etc). HTML is not the
place to be concerned whether your text is green or card has a ribbon.

------
swlkr
I came across tachyons a few years ago and it made CSS finally click with me.

The main advantage for me was that I didn’t have to switch back and forth
between two files to style something.

Utility-first CSS feels more like using a REPL than a compile-debug-reload
workflow.

------
meerita
I've wrote an extensive piece (p1: [http://minid.net/2019/04/07/the-css-
utilitarian-methodology/](http://minid.net/2019/04/07/the-css-utilitarian-
methodology/)) about this too called "In Defense of Functional CSS" (p2:
[http://minid.net/2019/08/12/in-defense-of-functional-
css/](http://minid.net/2019/08/12/in-defense-of-functional-css/)) I give all
the arguments I think are valuable for this discussion.

------
irrational
I skimmed the article, but I don't think it covered one of the reasons why I
prefer utility-first CSS. When all the CSS is in a separate CSS file I can
look at a page's HTML and have no idea what it will actually look like. But
with utility-first CSS, just by looking at the classes on the HTML elements I
can make a pretty good guess at what the HTML will look like when rendered.
I'm sure a lot of people won't see this as useful, but I really really
appreciate it.

------
51Cards
This was how I adopted CSS from day one. My standard home-evolved CSS library
has a large set of very simple classes that standardize the options I have to
choose from. As the article mentions one of the fallouts from this is
consistancy of design across multiple pages. I'd like to say I had some grand
epiphany about how CSS should be used but this just seemed like the most
obvious way to use it.

------
erikpukinskis
If you are building a totally generic CSS library to use on a bunch of
independent sites, then sure... utility first.

But the main reason I think semantic CSS is important has nothing to do with
anything technical.

CSS is not just a technical contract with the browser, it is the place where
your organization’s design language is made manifest.

If your pages match what’s in your designers’ mockups, that’s good. But if
your CSS matches what’s in your designers’ _heads_ that’s way, way better.

What that means is that “configurability” and “flexibility” and “composition”
are anti-patterns.

Being able to do anything is bad.

The goal is the opposite: almost everything should be impossible to do.

The goal is that you can only do things that make sense within the design
system.

That means making something that’s technically quite useless, but _just
barely_ can do the things your designers want to do.

The same applies to component names and arguments. That’s the other place
where the design system contract becomes real.

So, if you’re a freelancer than yes, go utility-first. But if you work on one
app day in and day out then you’re playing a different game with different
goals.

------
leephillips
I'd just like to mention that Jukka "Yucca" Korpela had some interesting
observations, relevant to the discussion here, about CSS back in 1997. He
might have been the first person to write about these issues:

[http://jkorpela.fi/styles/harmful.html#pos](http://jkorpela.fi/styles/harmful.html#pos)

------
goofballlogic
I think this is an issue which needs to be addressed a bit more holisticly.
The fact is that HTML, JavaScript and CSS (to name three) all use an element's
_className_ for slightly different purposes.

The author seems to consider BEM an example of a _semantic_ CSS scheme, but
really the semantic needs to be clear across all the consumers of the API
being implicitly established by the markup.

Ultimately HTML is the original source of a web page, with CSS and JavaScript
often augmenting this. For that reason, I think it makes sense to opt for the
HTML spec's definition of _className_ semantics when there is a clash.

The spec effectively balances the importance of both CSS and JavaScript (or
other user agent) uses, but cites an example useful to both:

[https://www.w3.org/TR/1999/REC-
html401-19991224/struct/globa...](https://www.w3.org/TR/1999/REC-
html401-19991224/struct/global.html#adef-class)

------
jspash
I think what people are really gravitating to with "utility CSS" when they say
they finally "get it" or it say "feels like REPL" is the fact that you can get
instant feedback in the browser using the inspector.

It's a bit like when you first "get" TDD. Which in my experience happens soon
after you've got your spec listeners and live reload hooked up properly and
manage to get the spec runner to react in less than 300ms. A whole new world
of possibilities open up.

I'm not taking sides, but just want to point out that this quick feedback loop
_might_ be clouding people's judgement as to the benefits and drawbacks of
using a coding style such as this.

------
luord
One vying for this approach can wax poetic as much as one wants, but for me,
seeing a difference between 'style="color: purple"' and 'class="color-purple"'
(with '.color-purple { color: purple }' in the css file) is very much the same
as seeing the emperor's new clothes. It looks and feels like indirection and I
am aware of duck typing.

The "it limits options" defense is not really here nor there, since ultimately
you could just rewrite all css rules into classes. Much like the style you can
add is infinite, the classes you can add are infinite.

------
aarondf
IMO, this is one of the best articles on utility CSS:
[https://adamwathan.me/css-utility-classes-and-separation-
of-...](https://adamwathan.me/css-utility-classes-and-separation-of-concerns/)

------
jpochtar
Just use inline styles and simplify your life. If you’re using
React/Angular/Vue/etc, your markup _is_ styling; so why are you separating
styling (html) from other styling (css)??

