As most developers know, there are many problems that can come up with CSS in a project. I will discuss a few common examples, and then share with you our solution to managing these issues.
Common CSS Problems in Projects
Legacy Code
Many projects will have at least one old CSS file that no-one knows what it does. People are scared to touch it, or delete things from it, just in case everything breaks. And so this mystery file remains.
Nesting
When I got started with SASS and discovered nesting, I nested everything. It seemed like the solution to all my problems! I could isolate the exact element I was trying to style in a very elegant way. But, the general-ness that makes it such an elegant solution, introduces problems all of its own. You may be trying to style one particular thing but you accidentally style several things at once. It also makes the code harder to read as you have to scroll up and down trying to figure out what the styling is trying to do.
!important
Sometimes - only on very rare occasions :-) - when you just need to get something done, front-end developers have been known to throw in an !important
or two. The hope is that it will fix everything and they will never have to deal with it again. Which, of course, is never the case!
Vague Filenames
Vaguely-named files make it difficult to know what goes where, and what each file might contain. For example, I have seen many projects with a file simply called modern.css
. A lot of time can be wasted searching for a particular piece of styling, or deciding where to put new styling.
Poorly Thought-out Class Names
For example, class="main"
. Naming things is famously very difficult, and the front-end is no different. When it comes to CSS, and the specificity hierarchy, having multiple developers contributing to the codebase and naming things in their own way, causes chaos. Styles override each other all over the place and there is no easy way to track down which style is being used in any particular situation.
The Solution: CSS Naming Conventions
When I began working for reinteractive, one of the first things I had to learn was the way we name things. Naming conventions differ from place to place but, luckily, the reinteractive way was very similar to the one I was already using.
I will cover the two conventions we use here at reinteractive. Following these guidelines are a great way to name things in the front end space, and can help address the issues I discussed above.
These conventions are:
BEM Features (block element modifier)
This is how we name the classes. Everything that you want to style should have a class. When we follow this methodology, things pretty much name themselves.
The general structure is block__element-modifer with the _’s and -‘s that way specifically.
block
is the header, footer, main content, etc.element
is the HTML element like heading, link, logo.modifier
is the styling for example size or colour
BEM makes everything element-agnostic. If you have a title and it’s h1 and later you want to change it to h2, it doesn’t matter because you’re not styling for the h1 or the h2, you are styling for the class name.
Here is an example for titles. A home page title has both a big version and a small version, and we also specify a footer title and a form title.
css
.home_page_title-big {
font-size: 3.45em;
}
.home_page_title-small {
font-size: 1.45em;
}
.footer_title-left {
text-align: left;
}
.form_title-hidden {
display: none;
}
By making the names very specific with those block elements, it eliminates any confusion. It also makes it less likely for someone to come in and add some styling that will override your code.
BEM Benefits
-
Eliminates accidental mis-styling Because the names are very unique and descriptive, they are only ever going to be in one spot so you can’t accidentally put in different styles.
-
Minimises rework A lot more thought goes into the planning stage, and you have already decided what it’s going to look like, so you rarely have to go back and retweak things.
-
Updating HTML won’t break the styling Having all our styling on classes instead of on elements means that if you do have to go in and update the HTML, it won’t break the styling.
-
Easier to find and update styling Every element has one class and all the styling for that class is in the one place. This means our styling happens in a very predictable way.
BEM Drawbacks
-
Very verbose (names can get quite long)
-
Difficult to have DRY code There can be multiple modifiers per class, which begins to add up. Note that there are ways around it, for example, SASS @extends, pseudo-classes, or commas.
-
High up-front cost Because we aim for whole project consistency, when starting a new project we put names on everything. This is done before commencing any work that is visible to the client.
ITCSS (Inverted Triangle CSS)
ITCSS is a methodology that visualises our entire CSS project as an inverted triangle with several layers, or sections. By following this hierarchy to organise our CSS files, we separate our codebase in the most effective way.
ITCSS Features
One of the features of ITCSS is that you end up with lots and lots of very small files. Each file is very specific and compartmentalised, and may have only 20 lines of code. Every block of styling gets allocated to its own file, and the structure goes from the general to the specific.
Low specificity: HTML, body, width - things that apply project-wide High specificity: this heading, this paragraph
Here is an example of one of my manifest files. It is for a Ruby on Rails + SASS project. This file would look slightly different for other languages, but the general principles are the same: ordering the files so they are applied from general to specific to prevent unintentional overriding:
css
//Manifest file
@import 'settings'; // variables
@import 'tools'; // mixins
@import 'generic'; // boilerplate
@import 'objects_typography';
@import 'objects_buttons';
@import 'objects_forms';
@import 'components_header';
@import 'components_footer';
@import 'components_content';
Let’s break it down…
First, I begin with the general things, settings
, which contains all my variables (colour variables, size variables, image variables), these are things I will use throughout the whole project.
Next is tools
, which contains mixins and media queries.
generic
is for generic reset boilerplate. This gets rid of all the browser styles and gives me a clean slate to work with.
objects_*
are little bits that are everywhere (buttons, forms, typography). I prefer to have a seperate file for each type of object.
Finally, components_*
are the parts of the actual website (headers, footers, content, …). Again, I prefer to have a seperate file for each type of component.
ITCSS Benefits
-
You know where you have to go to find a specific piece of code Everything is in its own very specific place
-
Descriptive and predictable names
-
Cascading is easier to manage with the inverted triangle structure, which results in more predictable styling
ITCSS Drawbacks
-
Filenames can get quite verbose This is necessary to identify which file will contain which styling
-
High upfront cost If there’s already CSS in the project, you have to split up all the different files and put the manifest in the structure
-
Project-wide approach ITCSS only works if it is used across the entire project. Therefore you must go through and change all the CSS to this new structure.
-
Difficult to implement if you are not using asset pipeline/compilers (this not a problem if you are using Ruby on Rails as it figures it out for you)
In Conclusion
- A combination of BEM and ITCSS
- Both have a high upfront cost
- But both make your codebase much easier to maintain
- More predictable styling
Since using these two methodologies, I often find the current me thanking the past me for having taken the extra time up front to get things set up properly. It certainly makes for a more easily maintained codebase down the line!
Resources
BEM
- BEM 101
- Naming #### ITCSS
- Managing CSS Projects with ITCSS