CSS: Styling HTML Elements Is A Trap
There is a nasty little CSS design pattern amongst us that makes our lives as front end developers harder. It’s quite likely that it slipped into your codebase, too.
CSS That Gets You Into Trouble
I’m sure we all have seen and done things like this:
// General typography for most pages h1, h2 { font-family: Georgia, serif; font-size: 2em; line-height: 1.2; text-transform: uppercase; } // Lists look nice with a padding li { padding-left: 2em; } // Every paragraph deserves a margin, right? p { margin-bottom: 1em; } // We only have this contact form, nothing else... input, textarea { border: 1px solid powderblue; box-shadow: 5px 0 whitesmoke; } // You get the idea ...
What’s Wrong About this?
This kind of CSS leads to unpredictable side effects and regression. Adjusting one of those elements might break other styles down the road.
After the above CSS, you work your way through the project. Sooner or later you end up doing this kind of stuff:
// Oh, new type of h2 headline ahead .teaser__headline { font-family: Helvetica, sans-serif; font-size: 1em; text-transform: none; // Particularly ugly } // This li element doesn’t need the padding .navigation__item { padding-left: 0; } // Dammit, sidebar paragraphs don’t need margins .sidebar p { margin-bottom: 0; } // Whoops, more than one form needed .header__search { border: none; box-shadow: none; background-color: cornflowerblue; }
Do you see CSS like that in your projects?
Solution: Always Scope To A CSS Class
We have all sorts of clever techniques to modularize and namespace our (S)CSS. So let’s modularize all of it and make no exceptions. The only reason to style elements globally is normalizing and resetting.
I moved towards this approach in my most recent projects and got a very robust and predictable code base. I only reset some element styles for a good baseline:
// Reset margin across browsers h1, h2, h3, h4, p { margin: 0; }
Everything else gets a module namespace:
.richtext { h1, h2 { ... } p { margin-bottom: 1em; } li { padding-left: 2em; } } // No overwrite necessary anymore .teaser__headline { font-family: Helvetica, sans-serif; font-size: 1em; } // Better, but should be improved by using classes .contact-form { input, textarea { border: 1px solid powderblue; box-shadow: 5px 0 whitesmoke; } }
Now there is no need to overwrite specific element styles anymore, like in the first example.
Never style elements – ever. Except for resetting.
Conclusion
We can make our lives much easier, by leaking as little CSS as possible from element styles into our modular CSS. The first step in that direction is not styling global elements at all. This is certainly not the only way of doing it, but it works very well in projects of any scale.
I would be interested in how you deal with issues like that and if this is of any value for you.