Garden Bird Themes
All Posts

My CSS Mindset

Published by Maureen Holland

I used to have Tim Gunn's catchphrase in my head during CSS development. A steady, insistent echo of “Make it work” encouraged me to brute force a lot of styles into place, condemning myself to a frustrating cycle of fixing something here only to find it was now broken there.

The cycle would only end when I had cobbled together enough mismatched properties and over-specific values to decently resemble the design. At this point, I would back away slowly and hope no change requests came in.

Every significant CSS task would turn into death by a thousand breakpoints. “Make it work” was clearly not working. I needed a new CSS mantra.

Be Water

Be Water, My Friend. Empty your mind. Be formless, shapeless, like water. You put water into a cup, it becomes the cup. You put water into a bottle, it becomes the bottle. You put it into a teapot, it becomes the teapot. Now water can flow or it can crash. Be water, my friend.

Recently, I was thrilled to hear a co-worker of mine say “My mind is at peace when I'm writing CSS.” Five years ago, I would not have known what she was talking about but today I feel the same way. It took a lot of work to get here and I wanted to share a bit of how that happened and what it means in practice.

The essential turning point was taking Heydon Pickering and Andy Bell's Every Layout course (now available for free!). I was already a fan of both developers from previous exposure to Pickering's Inclusive Components and Bell's Learn Eleventy from Scratch. But Every Layout blew my mind. I'd never had CSS explained to me that way. A lot of it went over my head at the time (some of it still does!) but the fundamentals stuck.

As designers, we seek to control the users' experience. But, as John Allsopp wrote in 2000's The Dao Of Web Design, attempting direct control over the way users consume content on the web is foolhardy.

CSS hates being told what it must do (i.e. width: 487px).

But it's very happy to take suggestions on what it should do (i.e. width: fit-content).

Therein lies the secret of CSS development: be the browser's mentor, not its micromanager.

I have two guiding principles inspired by this philosophy that have made a huge difference to both the quality of my CSS and the mental state in which I write it.

  1. Build the house before you paint the walls*

    If a website was a house, semantic HTML elements would be its load bearing walls. CSS would be the paint on those walls. If you need shelter (in web terms, content), you're gonna care about one of those things a whole lot more than the other.

    The best CSS is an enhancement. A website should still make sense when stripped of its presentational layer:

    • heading hierarchy is clear
    • links are links
    • buttons are buttons
    • images are appropriately sized

    Write the HTML first, without any thought of presentation. When you take off your HTML developer cap and put on your CSS one, you'll notice a lot of containers are already available as layout style hooks.

    Additionally, you can use the existing HTML structure as a way to focus your CSS decision making. There are often multiple approaches you can take to achieve the same visual result. Not all of these respect the semantic meaning of the document. Narrow down your options by identifying and discarding approaches that clutter or confuse the HTML.

    *I did not invent this metaphor. I heard it early days in my development career and have lost the source.

  2. Translation over imitation

    Designs have meaning. They create visual harmony on the page. That harmony relies on spacing scales and sizing hierarchies and color palettes. The values that make up those cohesive groups cannot be disconnected in the code or they will lose their meaning.

    This is where custom properties have flourished. Store those values on the :root and let components share access to them.

    #0060df is a single note that wants to be part of a chord.

    var(--blue-midtone) is human-readable and intentional. It encourages shared language with designers and conveys the relative value of this color within its palette to other developers.

    Has the designer requested this element to use a dark blue instead of midtone? You no longer need to return to the design file to look up that hex code. var(--blue-midtone) becomes var(--blue-dark) and you're done.

    Clear communication with your designer is essential at this stage. Understanding what the user wants and needs to do is paramount. You will ask “Why” a lot and your code will be better for it. You'll ask “What happens when...” and the design will be better for it.

    The design file is a screenplay; not a film. The finished product is a result of collaboration, not an assembly line.

Do not implement a design without understanding its purpose. It should work for screenreader users and keyboard-only users and visually impaired users. It should fit into a teapot and a bottle and a cup.

Be water, my friend.

More resources