Moving away from Tailwind, and learning to structure my CSS
Skip to main content
Hello! 8 years ago, I wrote excitedly about discovering Tailwind.
At that time I really had no idea how to structure my CSS code and given the<br>choice between a pile of complete chaos and Tailwind, I was really happy to choose<br>Tailwind. It helped me make a lot of tiny sites!
I spent the last week or so migrating a couple of sites away from Tailwind and<br>towards more semantic HTML + vanilla CSS, and it was SO fun and SO interesting,<br>so here are some things I learned!
As usual I’m not a full-time frontend developer and so all of my CSS learning<br>has happened in fits and starts over many years.
it turns out Tailwind taught me a lot
When I started thinking about structuring CSS, I was intimidated at first: I’m<br>not very good at structuring my CSS! But then I started reading blog posts<br>talking about how to structure CSS (like A whole cascade of layers or How I write CSS in 2024)<br>and I realized a couple of things:
Every CSS code base has a bunch of different things going on (layouts! fonts! colours! common components!)
It’s extremely useful to have systems or guidelines to manage each of those things, otherwise things descend into chaos
Tailwind has systems for some of these, and I already know those systems! Maybe I can imitate the systems I like!
For example, Tailwind has:
a reset stylesheet
a colour palette
a font scale
the systems I’m going to talk about
I’m going to talk about a few aspects of my CSS codebase and my thoughts so far<br>what kind of rules I want to impose on the codebase for each one. Some of them<br>are copied from Tailwind and some aren’t.
reset
components
colours
font sizes
utility classes
the base
spacing
responsive design
the build system
1. reset
I just copied Tailwind’s “preflight styles”<br>by going into tailwind.css and copying the first 200 lines or so.
I noticed that I’ve developed a relationship with Tailwind’s CSS reset over time,<br>for example Tailwind sets box-sizing: border-box on every element (which means<br>that an element’s width includes its padding):
* { box-sizing: border-box; }
I think it would be a real adjustment for me to switch to writing CSS without<br>these, and I’m sure there are lots of other things in the Tailwind reset (like<br>html {line-height: 1.5;}) that I’m subconsciously used to and don’t even realize are<br>there.
2. components
This next part is the bulk of the CSS!
The idea here is to organize CSS by “components”, in a way that’s spiritually<br>related to Vue or React components. (though there might not actually be any Javascript at all in the site)
Basically the idea is that:
Each “component” has a unique class
The CSS for one component never overrides the CSS for any other component
Each component has its own CSS file
So editing the CSS for one component won’t mysteriously break something in<br>another component. And probably like 80% of the CSS that I would actually want<br>to change is in various component files, so if I’m editing a 100-line component,<br>I just have to think about those 100 lines. It’s way easier for me to think<br>about.
For example, this HTML might be the .zine “component”.
And the CSS looks something like this, using nested selectors:
.zine {<br>...<br>&.horizontal {<br>...<br>&.vertical {<br>...<br>&:hover {<br>...
I haven’t done anything programmatic (like web components or<br>@scope)<br>that ensures that components won’t interfere with each other, but just having a<br>convention and trying my best already feels like a big improvement.
Next: conventions to maintain some consistency across the site and keep these<br>components in line with each other!
3. colours
colours.css has a bunch of variables like this which I can use as necessary.<br>Colour is really hard and I didn’t want to revisit my use of colour in this<br>refactor, so I left this alone.
The only guideline I’m trying to enforce here is that all colours used in the<br>site are listed in this file.
:root {<br>--pink: #fea0c2;<br>--pink-light: #F9B9B9;<br>--red: #f91a55;<br>--orange: rgb(222, 117, 31);<br>...
4. font sizes
One thing I appreciated about Tailwind was that if I wanted to set a font<br>size, I could just think “hm, I want the text to be big”, write text-lg, and<br>be done with it! And maybe if it’s not big enough I’d use xl or 2xl instead.<br>No trying to remember whether I’m using em or px or rem.
So I defined a bunch of variables, taken from Tailwind, like this:
--size-xs: 0.75rem;<br>--line-height-xs: 1rem;
--size-sm: 0.875rem;<br>--line-height-sm: 1.25rem;
Then if I want to set a font size, I can do it like this. It’s a little more<br>verbose than Tailwind but I’m happy with it for now.
h3 {<br>font-size: var(--size-lg);<br>line-weight: var(--line-weight-lg);
5. utilities
There are some things like buttons that appear in...