No Time Dad

A blog about web development written by a busy dad

How to Keep CSS Organized

Intro

Something I’ve learned about css files is that they grow quickly. Really quickly. They somehow become an unwieldy monster that I can never seem to tame, despite my best efforts. I sometimes feel scared to look at css files I wrote a week ago. They’re like a maze that I can’t find the way out of. I’m still deciding what the chaotic nature of css means and if anyone has solved this problem yet.

Sass seems like a good option for not getting lost in my own css maze, but I am always hesitant to add more dependencies even if I know they’ll improve my quality of life. Plus it is one more thing to learn. I think I have “old man developer syndrome” where I frown on new technologies and vigorously defend my habits.

Tailwindcss is another option that tries to (or eliminate) wild css files by using utility classes in the html. I do like this approach, but I worry that it replaces hard to maintain css files with hard to maintain html files. There is no question that the folks at tailwind are excellent developers and have created great products, but I haven’t gotten on the utility class train yet. Mostly due to my own stuborness.

I like writing plain html and css, so I am trying a few different techniques to try and keep my css files more organized and coherent. Most of these are new to me, but I think people have been using these techniques for a while.

Follow the structure of the html

The first technique is to structure my css so it follows the same structure as my html file. What that means is that if I have a parent div and a child div, then I would make sure the parent div’s selector is defined above the child div’s selector in the css file.

<div class="Parent">
  <div class="Child">...</div>
</div>
/* Good */
.Parent {
  ...
}

.Child {
  ...
}


/* Bad */
.Child {
  ...
}

.Parent {
  ...
}

This also applies to the entire html file itself. If I had an element at the top of my html file, then I should have any selectors it uses at the top of my css file too. If I opened an html file I hadn’t looked at for a while, I can assume that my header element’s selectors will be at the top of my css file. The maze is becoming easier to escape from.

<html>
  ...
  <body>
    <header>...</header>
    <main>...</main>
    <footer>...</footer>
  </body>
</html>
/* Good */
header {
  ...
}

main {
  ...
}

footer {
  ...
}


/* Bad */
footer {
  ...
}

main {
  ...
}

header {
  ...
}

It’s likely that I’ll be adding css selectors to existing files in the future. It’s important to not add selectors to the css file without considering the order of the existing selectors and how they correspond to the html. Using the example above, if I added a new section element after the main element in the html, I then need to define the css selector for the section between the main and footer selectors in the css. Otherwise, the entire system is thrown off and you’re deep in the maze again.

Naming conventions

Naming selectors is hard. This is part of the reason tailwindcss and other utility css frameworks exist. It’s one more thing you have to think about and get right. Poorly named selectors make css files difficult to read and understand. Renaming selectors can be painful too. Even when I’m trying to do the right thing and give selectors a good name, I also have to go to another file and replace all of the places where I used the original name. My editor (vscode) doesn’t do this automatically, unless I am missing something (if I am please, I beg you, tell me).

So the style I have adopted for naming my selector is Block Element Modifier, also known as BEM. It might be an old-school approach, but if I use it correctly I notice a difference when I look at css I wrote weeks or months ago.

I tend to use React a lot when I am working on small projects, so my naming style isn’t the “traditional” BEM way, but it works for me. I use css modules when working in React, so I add selectors to elements via className={styles.Block__Element__Modifier} instead of className={styles["Block__Element--Modifier"]}.

I try not to get hung up on having selector names perfectly match the parent and child elements. At the end of the day I want to finish projects and not spend all my time making sure my css is perfect. My working time for side projects is limited, after all.

Refactoring

This is the technique that has had the most profound impact on the readability and maintainability of my css files. Coincidentally, refactoring is also the most difficult technique for me. It’s is tough because there isn’t the concept of unit tests for css. When I remove or change a selector I am often just reloading the page to see if anything broke. This is tedious, but effective.

A couple tips for refactoring:

  1. Start by refactoring properties instead of entire selectors. Moving or removing one property at a time is slow, but less error prone.
  2. Look for duplicates. CTRL-F in the css file for properties and values like ‘color: white;`. If you get a few results, then start looking for ways to remove them.

Conclusion

None of these solutions are great, but I think they do improve my quality of life when writing css. Having my css follow the structure of my html is probably my favorite technique since I don’t have to think about it too much. No surprise that refactoring is my least favorite but most rewarding technique. Removing code is wonderful.