Reflections on “CSS Refactoring” by Steve Lindstrom

by 

| November 11, 2020 | in

Why I Read This Book

I’ve worked in software development professionally for about six years, throughout which much of my time has been spent in front-end web development. In that time, I have written my fair share of CSS and Sass, but I have never felt especially competent while doing so.

I can typically style a web component to match a design specification eventually, but it may take me a while, and I may feel that the solution is dirtier than I’d hoped it would be. I suspect this sentiment is shared by many developers. CSS is something a lot of us pick up along the way through trial and error, learning only enough at a time to accomplish the task immediately in front of us. It should be no surprise then that we end up cobbling together stylesheets that no sane person wants to try to understand or maintain.

So it has come to this. I have reached my breaking point, and I have decided I must and will improve my CSS skills. My first step in this journey was to read a book that I happened to pick up in a Humble Bundle of web development books some months back (side note: I love Humble Bundles). I will spend the rest of this post reflecting on my takeaways from the book.

Perspective on CSS

In the first chapter of CSS Refactoring, the author reflects on the basic tenets of good software architecture. CSS tends to be a bit of an afterthought in my mind when developing web components, so this first chapter gave me a revelation that, in hindsight, should have been obvious a long time ago.

The architecture of stylesheets should be given a rigorous first-class consideration when developing a website or components in a website. Classes and styles should not be shoved into place as an afterthought. Consider crafting stylesheets with the following basic software architecture principles:

  • Good styles and stylesheets are predictable
  • Good styles and stylesheets promote code reuse
  • Good styles and stylesheets are extensible
  • Good styles and stylesheets are maintainable

For the matter, stylesheets need to keep up with modern times and best practices, just like any other piece of a tech stack. Best practices constantly evolve, and a developer must invest time into staying relevant and leaving behind the obsolete.

It’s easier to prescribe the above four principles than it is to apply them in real life. This book provides a methodical process for writing and refactoring CSS, which I look forward to implementing in my own projects.

Organizing CSS and the Cascade

“When styles are classified and used in relation to their intent, finding ways to reuse code becomes much more obvious.” – Steve Lindstrom, CSS Refactoring

CSS Refactoring gives a great overview of how “the cascade” works in CSS and selector specificity. I imagine that it is mostly review for many developers, but it’s always good to have a refresher. Also, it prepares the reader for the following suggested structuring of a stylesheet:

  • Normalizing styles
    • Use these to get a consistent starting point when dealing with the different browser-specific user agent stylesheets (e.g., body { margin: 0 }).
  • Base styles
    • Use these to set the generic styles on primitive elements that should look the same across your website (e.g., h1, p).
  • Styles for components and their containers
    • Use these to style the innards of the different building blocks of your website.
  • Structural styles
    • Use these to style the structure of the components and their containers in your website (think layout and dimensions).
  • Utility styles
    • Place your important (!important) styles here, classes that are applied via JavaScript, and other classes that serve a singular purpose.
  • Browser-specific styles (if necessary)
    • Place any unfortunate CSS that is required to get the desired effect in stubborn browsers.

This orders styles in such a way that the most specific selectors naturally fall towards the end of the cascade. Note that media queries are not listed on their own as they should be placed after their relevant declaration blocks. Note also that each of these types of styles is covered in much greater detail in the book.

I’m a fan of putting coding style guides into the documentation of projects regardless of the number of developers that may work on it. That said, I’d not considered including a CSS style guide into a project until now. Simply calling out the desired structure of a stylesheet using the aforementioned six sections could do wonders for maintainability.

Testing CSS

I’m saddened but not surprised to hear that there is no silver bullet that makes it simple to regression test CSS changes. Most of the methods discussed in this book around visual regression testing involve either taking screenshots and eyeballing the difference between the website’s current state and the screenshot or using some tool to effectively do the same thing.

A few of the tools discussed in brief are:

These tools facilitate the taking of before and after screenshots with a visual “file diff” that makes changes painfully obvious. I’m not sold on this concept from a practicality standpoint, but I do find these tools kinda neat.

Refactoring Strategies

Another tool discussed at length in this book is a Chrome plug-in, CSS Dig. I’m more of a Firefox guy myself (shout out to Firefox Developer Edition), but I will use Chrome if I must. CSS Dig can be used to analyze a website’s CSS and provide a ton of information on how selectors are being used. If you need to take stock of the current state of your styles, this may be worth looking into. It can give you insights such as:

  • Redundant declarations of selectors
  • Reference count of selectors
  • Unnecessary uses of the !important keyword
  • Overly complex or specific selectors

And so on. After taking stock of your styles, the following steps are suggested to be performed in order while refactoring:

  1. Ensure CSS is consistently structured
  2. Remove dead code from stylesheets
  3. Decouple CSS from your JavaScript
  4. Establish base styles
  5. Convert selectors using ID’s to classes
  6. Separate out utility styles and look for unnecessary uses of !important
  7. Define reusable components
  8. Remove inline styles

In this way, you can eat the proverbial elephant (one bite at a time) by iteratively improving your stylesheets.

Generally Good Practices

Build A Pattern Library

What is a pattern library? I’m glad you asked. Consider creating a “pattern library” page which takes all the basic UI elements from a design specification and puts them all together neatly in one spot for all to see and review. This could be a great reference for developers and designers alike to come back to over time and provide a way for designers to scrutinize all the elements (depending on their level of involvement; assuming you are working with dedicated design folks).

Separation of Concerns

One important takeaway from this book is the separation of concerns between CSS and JavaScript. The author provides a few simple suggestions to accomplish this.

The ID Attribute

If an ID attribute set in HTML is necessary and used by JavaScript, do not use that same ID in a CSS selector. Further, the author suggests prepending IDs that are used in JavaScript, so it’s obvious just by reading the markup. This will also make it more obvious that the ID should not be placed in a stylesheet. For example:

As a general rule of thumb, do not use IDs in CSS selectors. This is an indication that the style is too specific, as it may only be used for a single thing on a page. If the style of an element must be made more specific but does not warrant a class on its own, consider adding more specificity by adding the parent container to the selector.

Add Classes with JavaScript, Never Styles

If the style of an element must be manipulated through JavaScript, then accomplish this by adding or removing classes but do not add or remove styles directly. Adding or removing styles directly in JavaScript is a clear violation of the separation of concerns between a script and a stylesheet.

What’s Next?

Not satisfied with my reflections? I recommend picking up the book. It’s a fairly short read as far as tech books go. As for me, I plan to continue my quest to level up in web development by reading and reflecting on Jeremy Wagner’s Web Performance in Action and Working with Static Sites by Raymond Camden, Brian Rinaldi. Stay tuned for that – it’s going to be wild.

References

CSS Refactoring by Steve Lindstrom