We have to admit it. Most of us don't like their CSS code!
When you start a new project, you feel very excited and you say “Ok, this time I'm gonna make my CSS as clear and maintainable as I can.” However, most of the time — as the project grows — we start feeling unhappy about it. It's so messy, unorganized, and hard to change.
Before I start, I have to say that I'm not the most experienced one at writing CSS. However, over the years I started to learn and look for the best ways and techniques that make my CSS, at the very least, easy to change.
I can't imagine these days anyone writing their CSS “purely” — without a preprocessor! In simple words, CSS preprocessors are those tools that add the things that should've been in CSS in the first place.
I can't imagine writing my CSS without using variables, mixins or without nesting my selectors to where they belong. There are countless reasons why you should use a preprocessor — those are just a few of them (search for more).
So, it's most likely you're using one (and I assume that, because the rest of the tips depend on this). However, if you're not yet, I encourage you to check out the available tools and choose the one you like (they are very easy to learn). For me, I like using stylus.
Nothing is better than knowing where to find the CSS styling rule you're looking for. When you organize your CSS in a good way, you'll get the power of jumping to what you want in a second or two!
By organizing I mean to separate your CSS into files. Each file containing the styling for only one thing (element, or multiple related elements).
For example, I organize my CSS into four classes (not CSS classes!):
The way I organize these files is by putting them in the respective directory. So, I would have a directory named components, and another one named layout, and so on.
After that I start importing them in my main app.styl file. Here's an excerpt from my blog's source code:
/** Bootstrapping */
@import 'vendor/Normalize'
@import 'Mixins'
@import 'Colors'
@import 'Typography'
@import 'Links'
@import 'Lists'
@import 'Overrides'
/** Component */
@import 'Components/Button'
@import 'Components/Widget'
// …
/** Layout */
@import 'Layout/General'
@import 'Layout/Header'
@import 'Layout/Navigation'
// …
/** Utilities */
@import 'Utilities/Overlay'
You can't imagine how much time mixins can save you. Once you know how to write them, you'll find many uses for them.
In case you don't know what a mixin is, it's like a function that you call with parameters, but it doesn't return anything. Instead, it spits out everything you define in it — after it evaluates the conditions and the like (if there's any).
For example, I like to define a mixin to help me styling the three states of an element all at once. Those states are: hover, active, and focus. So, I usually call it haf
.
Here's how it looks like (I'm using stylus here):
haf(element, includeSelf=false)
if includeSelf
{element}, {element}:hover, {element}:active, {element}:focus
{block}
else
{element}:hover, {element}:active, {element}:focus
{block}
This means from now on, I can write this:
.Button
background: red
+haf('&')
background: blue
Instead of this:
.Button
background: red
&:hover, &:active, &:focus
background: blue
Although for some people it's not a big deal, I think it saves a little bit of time and makes your code cleaner in the long run.
Have you ever found yourself forced to use !important
to apply some styling on your elements? It doesn't feel good, does it?
This is because you're adding weight to your CSS selectors. By weight I mean, you precede your selector with other selectors (i.e. parent elements).
For instance, let's say you're building a modal box component. And its layout looks something like this:
<div class="modal">
<div class="container">
<div class="header">
<h1 class="title"></h1>
</div>
<div class="content"></div>
<div class="footer"></div>
</div>
</div>
Let's say now you want to style the title in the header. How would you do it? The traditional way is to do something similar to this:
.modal .container .header .title {
// Your styling goes here
}
But this is not good; you're adding more weight to your selector. This means, if you try to override it later in another place, you'll have to specify the whole selector, or you'll have to use !important
.
In case you're wondering why you would override the styling in other places, think of using this modal inside another div with class .foo
, and you want it to look differently than the one without the .foo
div.
In this case you'll need to specify the whole selector like this:
.foo .modal .container .header .title
Too much weight!
So, we talked about the problem, let's see how to solve it.
Actually, there's nothing too special you need to do about it other than following some naming convention.
The best naming convention I've been using so far is called BEM (Block-Element-Modifier). If you're not familiar with it, check out this css-tricks blog post: “BEM 101”.
After you start using BEM, you'll start noticing a huge improvement in your CSS, and writing one-level deep selectors is one of them.
I have to say it: “Flexbox is the best thing ever happened to the CSS language so far!”
It's been a while since the release of Flexbox, and yet very few people use it in their projects. You can't imagine how easy Flexbox can make your life.
I can't say what you can do with Flexbox in this short section, but I can assure you that once you know how to use it, you'll be able to style your layout in any way you can think of in a very short time — and without using any hacks.
The only problem with it, though, is that some people find it a little bit hard to learn; luckily, it's no longer the case with the awesome screen casts made by . You can find them at flexbox.io.
So, you now know how much I love Flexbox, but what about CSS frameworks? My answer is they are very good, but only for prototyping.
I used to use bootstrap in all of my projects. However, I never felt very happy seeing my html bloated with tons of md-col-3
and other classes. Not just that, but I also faced many situations where I couldn't style something the way I exactly wanted.
All those problems and more disappeared when I started using Flexbox and writing the CSS for my layout by myself.
It's normal to have a number of primary colors for every website you build. The problem some people have with colors is they find some difficulty changing them.
I've been in many situations where my client requests to change some color 3 or 4 times; I can do it in 1 second!
The good thing is that it's very simple to do!
Just define your colors using CSS variables — your preprocessor helps you with that. I usually do it in the bootstrapping section (which we talked about earlier).
So, basically, I create a file called colors.styl and put in it almost all the colors I use in the website.
And I usually divide the file into sections, like this:
/* Primary Colors */
$dark = #081444
$light = #0064a3
$white = white
/* Layout */
$bg_color = #ffffff
$light_gray = #f0f0f0
$gray = #C0C0C0
$dark_white = #fafafa
$red = #ee3333
/* Typography */
$black = rgba(0, 0, 0, 0.8)
$dark_gray = rgba(0, 0, 0, 0.4)
$selection_color = rgba(0, 100, 163, 0.6)
Another thing I find useful doing is to define the colors with their names. For example, if I'm sure that I'll use the red color, I define a color called $red
. That color shouldn't be pure red; it could be a variation of the color.
Utility classes are those classes you define once and use on multiple elements. An example of this is a class that floats an element to the left or right. Or maybe a class that adds some shadow to an element.
It's usually pretty useful to prefix your utility classes with something like “u-”
just to be able to distinguish it later.
Although they are very useful, you should be careful not to overuse them. If you overuse them, you'll end up building your own CSS framework! Which you don't want to do, because we already have tons of these — don't reinvent the wheel!
In some situations, you'll find yourself in a need to change some styling for a library you're using.
In those cases, it's okay to use !important
.
But to make things even easier, I find it so helpful to dedicate a whole file (or multiple files) for overrides.
So for example, let's say you're using a library for syntax highlighting. And, you want to change something you don't like. Or probably you want to change a color so it matches your website's theme.
Either you create a file and call it overrides.styl, or a directory called overrides and put in it a file for each library you want to change.
Then, you'll start doing your changes either by matching their selector weight, or by using !important
.
With that, you'll have a clear place for all your overrides instead of mixing things up.
Those were my 8 tips on writing clean, maintainable CSS. You may not like them all. So, choose the ones you find useful to you and feel free to change them to your taste.
What are yours? Do you have some tips that you find useful? We'll be very glad if you share them with us in the comments.
I'm a freelance web developer. Laravel & VueJS are my main tools these days and I love building stuff using them. I write constantly on this blog to share my knowledge and thoughts on things related to web development... Let's be friends on twitter.