CSS at trivago — Part 2: Naming Conventions and Methodologies
ACSS? BEM? OOCSS? SMACSS? BEMIT? UCSS? Atomic OOBEMITSCSS?
What is wrong with CSS? Or are we wrong with all those conventions and methodologies? Are they really necessary? Which problems do we want to solve?
The second part of my series will focus on CSS naming conventions and methodologies and explain how and why we incorporate some of them in our large scale environment at trivago.
Specificity issues, lack of reusability, problems with maintainability, speed, and quality of development have been some challenges we struggled with in the past. The specificity graph from trivago.com 2012 is a good indicator for this:
Working with this CSS base proved to me that every minor change to any CSS class caused from one to an infinite number of side effects with other elements or pages. It was a mess. The only way to get out of this trouble was to create another even more specific selector, just to be sure.
We reduced this specificity graph a lot by setting up a dedicated Front-End team, tackling a few facelifts and rounds of refactoring based on some very simple guidelines.
Our guidelines were quite simple in the past
The convention was simply `my_selector`, do not nest more than 3 levels and a bit of common sense. In a small team this this worked pretty well, but as the team grew and more people started to work on the codebase the reusability suffered. In addition, the aforementioned guidelines left a lot of room for interpretation. As long as one person worked on a stylesheet everything looked good, but the more people started to work on the same area the code became more and more unmaintainable. We needed something more strict, conventions to make it easier for people to write CSS within a set of guidelines everybody can easily follow, adapt and understand.
We could have created our own methodology. There are already too many reinventions of the wheel and also applying some of the already existing methodologies might help get new developers on board more easily.
BEM, OOCSS and functional CSS
BEM looks ugly. You might think. Also it may “blow up” your HTML with classes. With many classes. But it scales. We needed to tear down the specificity wall and make our components more stand-alone. Also it offers a clear guideline how to name blocks, elements and how to mark modifiers.
Let’s have a look at buttons. Buttons are always used as a BEM example, I’ll follow that tradition.
Let’s have look at the CSS:
Defeat the overwrites
One thing which happened in the past and was one of issues with our specificity graph have been overrides and I mean a lot overrides. Overrides everywhere. In the example above you can see that only one property from a modifier overwrites a property from the component itself in this case it is the border definition. BEM helped us to keep our specificity low, reduced the amounts of overwrites and made components more modular.
Combine it with OOCSS / functional CSS
But it came with a down-side. BEMifying all the things would have meant to write a lot of CSS. While we maintain some very component heavy products we also need to provide an easy way to customize some templates e.g. for CMS purposes to adapt to the Design System without writing CSS all the time. So in addition to BEM, we introduced OOCSS and functional CSS classes. E.g. we have a set of classes which handles spacing, margins etc. A wrapper, headline or any other elements should have a margin which is four times the default spacing? We add a class to the element e.g. `<h1 class=”space-4”>`. Those functional CSS classes are not `!important` and therefore are contained in our objects layers of our ITCSS structure. As of this they cannot be used to trump component behavior, as those should be immutable. But they can be used to “enhance” components. E.g. we can float a component, if it does float by default or with a modifier with e.g. `<section class=”pull-left”>`.
Let’s have a look at an — again very basic — example. The following screen shows the alert components within our Pattern Library
I’ve highlighted with the chrome inspector the second container for the alert information. All alerts are listed inside a section called UI toolkit inside the Library and we use a separate layout for this. As the alerts itself shouldn’t have any margins, we put a container around which gets the class `mb-gutter` for adding a margin bottom with the default spacing value defined in our Design guidelines.
We need to be careful with those functional CSS classes as they can be abused, but we do have a very strong code review culture where we discuss this.
Of course all this ends up in some circumstances that a HTML element has up to 10 classes. People don’t like this, but to be honest, if you craft a clean and sustainable HTML structure does it really matter whether you have some more classes in the class-attribute than you are used to have? Does it matter for semantics and accessibility?
So there is all in all nothing really special with our naming conventions and guidelines. In general we try to keep it just simple and avoid over-engineering the things. All of what we have changed in the last months has helped us to build a lot a more sustainable and healthy CSS base.
But combined with the ITCSS approach it helped us to tame down the complexity of our CSS and now we have a much nicer specificity graph:
The next article of this series will be about testing CSS, documentation, and releasing.