How To Avoid Spaghetti CSS and Still Feel Fast and Productive

Ever feel like you are just slapping classes on HTML elements, throwing a bunch of properties and values in your CSS, and the next thing you know you have a 500-line monster of a CSS file?

I've been there.

First comes file monstrosity. Then, when CSS files grow too large, you split it up into multiple files, but really you are just kind of spreading the spaghetti around.

Then comes the specificity hell.

Classes overriding classes. Adding styles and screaming "why isn't this style changing!!". Finally yelling "screw it" and using <strong>!important</strong> 22 different times.

Why do we fall into the spaghetti CSS code trap?

Because we love CSS. We love seeing things come to life in the browser.

We love being able to quickly iterate and when things line up how we want, we feel a strong sense of accomplishment and want to move on to the next line of CSS.

"Oh well I can come back and refactor that later if I need to."

But do we ever come back to refactor? Usually not. Why? Because we need to make quick changes and rather than untying a knot, we can just add another class to overide the existing class.

Thus, all-you-can-eat spaghetti!

So how, then, can we combine speedy CSS writing while also avoiding said spaghetti?

Let's take a 3-pronged approach.

  1. CSS (or Sass) file organization
  2. Semantic Class Structures
  3. Property and Value Ordering within a class

1. CSS (or Sass) file organization

Even if you haven't written Sass yet, start learning Sass through file organization.

You can write vanilla CSS in a Sass file.

Our Sass file and folder structure will look something like this:

  • /modules
    • _widgets.scss
    • _postSummary.scss
    • _postSuggestions.scss
  • /globals
    • _typography.scss
    • _lists.scss
  • main.scss

In the above example, we have divided our modules and global styles into folders, each containing file partials.

Our compiler (Prepros is a GUI drag-and-drop compiler) will ignore these partials and only compile our main.scss into main.css.

Therefore, our main.scss will contain an @import statement for each partial in our two folders. It will look something like this:

/* main.scss */ 
@import 'globals/typography'; 
@import 'modules/widgets'; 
@import 'modules/postSummary'; 
@import 'modules/postSuggestions';

How do you decide on your Sass folder structure?

Great question!

Breaking things up into different files is for your benefit.

Afterall, everything will eventually be compiled and minified down into a one or a few CSS files.

I break up files into modules and globals.

Global File Partials

If you are building a WordPress theme, for example, you can create a typography global partial (ex: _typography.scss), with basic typographic hierarchy.

This makes perfect sense, since articles and blog posts will be a staple content structure.

If you are building a web app, it may be more advantageous to have, say, an icons partial (ex: _icons.scss) in your globals folder.

Keep your global Sass files light and generic.

For _typography.scss in a WordPress theme, I may just declare font-family, line-height, font-size across breakpoints, and margin-bottom so things stack nicely.

I would avoid declaring things like special padding to accommodate icons next to a font, or special colors. These special cases can be part of a module.

For an _icons.scss in a web app build, I may just declare the file paths to the icons themselves. Nothing more.

These global declarations will be element-level styles, so be very judicious when creating them, or you can fall back into override hell.

Think of your global partials as a thin layer of your own custom CSS normalize.

Module File Partials

Modules are basic groupings of HTML element structures or combinations. There are no hard and fast rules here as to how many elements are in a module. Whatever makes most sense to you and your project structurally and semantically.

For example, let's say you have a new module you decided to title _postsNextPrevious.scss

Let's assume this component consists of a headline, thumbnail image, an arrow icon, and is wrapped in a block-style link.

If instead you decided to create _thumbnails.scss, _headlines.scss, and _block-link.scssfile partials, you would now be working across four different files, just so it can all be "reusable and modular".

Remember, the goal isn't to create a Bootstrap-like framework, the goal is to create maintainable project-specific Sass.

What really matters is being able to work efficiently, and communicate with others. Massive separation of concerns across Sass files will kill efficiency and communication.

If you can tell a manager about your progress on the timeline display widget, and talk to the backend dev about the data you need from the API for the timeline display widget, and be working in a HTML file titled timelineDisplay.html and a Sass file partial called _timelineDisplay.scss, then all your coding and business requirement worlds are in alignment.

What a joy! Work is fun again!

You can deliver things faster, optimize or refactor easier in the future, and ultimately build cooler stuff because your mental bandwidth isn't tangled up in file separation.

2. Semantic Class Structures

In general your Sass files should contain mostly classes, and use a consistent syntax structure to indicate what is a baseline class, and what classes are modifiers or states of the baseline class.

BEM is a syntax structure. It stands for Block-Element--Modifier.

Think of a block as a module in our file structure examples. Same concept, different name.

Then, think of an element as a single HTML structure within the module.

The modifier could be a state or variation of the overall module or an element within the module.

Therefore, in our above _postsNextPrevious.scss example, we may have the following classes:

/* _postsNextPrevious.scss */ 
/* module */ 
.postsNextPrevious { 
    display: inline-block; 
    width: 50%; 
    background-repeat: none; } 
/* module modifiers */ 
.postsNextPrevious--previous { 
    background-image: url(images/icon-left.svg); 
.postsNextPrevious--next { 
    background-image: url(images/icon-right.svg); 
/* elements */ 
.postsNextPrevious-title { 
    /* title styles here */ 
.postsNextPrevious-thumbnail { 
    /* thumbnail styles here */ 

3. Property and Value Ordering within a class

Here, you can take whatever approach you wish, but I prefer to order properties by 4 main categories.

  • Display and Positioning props (flex, grid, relative, absolute, etc.)
  • Dimensional props (height, width, padding, margins, etc.)
  • Typography props (fonts, letter-spacing, text-shadow, etc.)
  • Decorative props (backgrounds, colors, box-shadow, etc.)

Organizing and ordering properties will speed up your writing process.

It may also reveal properties which are default to a class, and which need to be separated out into modifier classes.


Having a consistent approach to...

  1. File structure
  2. Class naming
  3. Property organization

...makes CSS and Sass writing a faster, more enjoyable experience.