10 Best Practices for Improving Your CSS
Building scalable and manageable stylesheets
CSS may seem like a pretty straightforward language, on that’s hard to make mistakes in. You just add your rules to style your website and you’re done, right? With small sites that require only a couple of CSS files, this might be the case. But in large applications, styles can quickly spiral out of control. How do you keep them manageable?
The reality is that, just as with any other language, CSS has its own nuances that can make or break your design. Here are 10 tips for CSS — best practices that can help you bring out the best from your styles.
1. Do You Really Need a Framework?
First of all, decide whether you really need to use a CSS framework. There are now many lightweight alternatives to robust frameworks. Usually, you won’t be using every selector from a framework, so your bundle will contain dead code.
If you’re only using styles for buttons, outsource them to your own CSS file and get rid of the rest. Also, you can identify unused CSS rules using code coverage in DevTools.
To open it, search for Coverage in the Tools panel. You can open the Tools panel by clicking
P. Once open, start recording by clicking on the reload icon. Everything shown in red is unused.
You can see that in the example above, it says that 98% of the CSS is not used. Note that this is not actually true — some CSS styles are only applied after the user interacts with the site. Styles for mobile devices are also flagged as unused bytes. So before you remove everything, make sure you verify that it is indeed not used anywhere.
2. Prefer Using a CSS Methodology
Consider using a CSS methodology for your project. CSS methodologies are used to create consistency in your CSS files. They help in scaling and maintaining your projects. Here are some popular CSS methodologies that I can recommend.
BEM —Block, Element, Modifier — is one of the most popular CSS methodologies out there. It’s a collection of naming conventions you can use to easily craft reusable components. The naming conventions follow this pattern:
.block: Blocks represent a component. They’re standalone entities and are meaningful on their own.
.block__element: These are parts of a
.block. They have no standalone meaning and must be tied to a block.
.block--modifier: These are used as flags on blocks or elements. We can use them to change the appearance, behavior, or state of elements. For example, to use a hidden flag, we could say
Inverted Triangle CSS helps you better organize your files by introducing different layers to different specificities. The deeper you go, the more specific.
Object-oriented CSS, or OOCSS, has two main principles.
Separating structure and skin
This means you want to define visuals separately from structural code. What does this mean in practice?
2. Separating container and content
This means you don’t want any element to depend on its location. The same elements should look the same regardless of where they are on the page.
3. Set Up a Pre-Processor
Setting up a pre-processor can benefit you in various ways. A pre-processor is a tool that lets you use advanced features that don’t exist in CSS. These can be things like variables for loops, or even functions.
There are plenty of pre-processors out there. Probably the most famous three are Sass, Less, and Stylus. I recommend using Sass because of it’s thriving community and the extensive documentation you can find for it on the web.
So, how can pre-processors help you?
Organize your styles better
Pre-processors help you organize your styles better. They have the ability to break down your files into smaller, reusable pieces. These can be imported into each other, or later separately into your application.
Nest your selectors
Another great way to enhance readability is by nesting your selectors. This is a simple, powerful feature that CSS lacks.
The hierarchical structure makes it easier to visualize how different elements tie together.
Automatically vendor prefix your rules
Some nonstandard or experimental features are prefixed in CSS. Different browsers use different prefixes for them, such as:
-webkit-: for WebKit based browsers such as Chrome, Safari, or newer versions of Opera.
-moz-: for Firefox.
-o-: for older versions of Opera.
-ms-: for IE and Edge.
To support all major browsers, we have to define certain properties multiple times.
Pre-processors help us tackle this with
mixins — functions that can be used in place of hard-coded values.
Instead of writing out the same thing over and over again, you can just include
mixins whenever you need them.
An even better option is a post-processor. A post-processor can run additional optimization steps once your CSS is generated by a pre-processor. One of the most popular post-processors is
You can use
PostCSS to automatically prefix your CSS rules, so you don’t have to worry about leaving out major browsers. They use values from Can I Use, so it’s always up to date.
Another great post-processor is
autoprefixer, when you want to support the last four versions — you’re all done without having to write any vendor prefixes in your CSS files!
Use configs for consistent designs
mixins, you also have the option to use variables. In conjunction with a linter, you can enforce design rules.
4. Use Markup Instead of CSS
Now let’s move on to actual CSS. This is often overlooked. Usually, you can reduce the size of your CSS bundles by simply using the correct HTML elements. Say you have a heading with the following set of rules:
You’re using a
span element as a header. You override the default display, spacing or font style. This can be avoided by using an
h3 instead. By default, they have the styles you’re trying to achieve with other elements. You can immediately get rid of four unnecessary rules.
5. Use Shorthand Properties
To further reduce the number of rules, always try to go with shorthand properties. For the above example, we could have said:
This is true for other properties such as paddings, borders, or backgrounds.
6. Reduce Redundancy
This goes hand in hand with the previous point. Sometimes it’s hard to spot redundancy, especially when repeating rules don’t follow the same order in both selectors. But if your classes differ in just one or two rules, it’s better to outsource those rules and use them as an extra class. Instead of this:
Try to go with a similar approach:
7. Avoid Complex Selectors
There are two major problems with using complex selectors. First, your increased specificity will not only make it harder to later rewrite existing rules, but also increase the time it takes for the browser to match selectors.
When your browser is trying to interpret selectors and decide which element it matches, they go from right to left. This is faster in terms of performance than doing the other way around. Let’s take the selector below as an example.
Your browser will first start from the
span. It will match all the
span tags then go to the next one. It will filter out the
spans that are inside a
.selector class, and so on.
It’s not recommended to use tags for CSS selectors because it will match for every tag. While the difference can only be measured in a fraction of a millisecond, little things add up. More importantly, it’s good practice to reduce complexity for another reason.
Understanding the selector
It’s not only hard for machines to parse, but it’s also hard for humans to do so. Take the following as an example:
Now it looks much more pleasant. If you still find yourself in need of an overly complicated selector and you believe you have no other option, please leave a comment below explaining your solution.
8. Don’t Remove Outlines
This is one of the most common mistakes developers make when writing CSS. While you may think there’s nothing wrong about removing the highlight that outlines create, in fact, you’re making the site inaccessible. It’s common practice to add this rule as a reset to your CSS.
This way, however, users with only keyboard navigation will have no clue about what they’re focusing on your site.
If the default styling looks bad for your brand, create custom outlines. Just make sure there is some kind of indication when it comes to focusing elements.
9. Use Mobile First
When you have to deal with media queries, always use mobile-first. The mobile-first approach means you start writing CSS for small screen devices first and build from there. This is also called progressive enhancement.
This will ensure that you mostly add extra rules to cater for large screen devices, rather than rewriting existing CSS rules. This can reduce the number of rules you end up with.
How can you tell if you use mobile-first? If your media queries use
min-width, you’re on the right track.
Lastly, compress your bundles to reduce their size. Compression removes comments and whitespaces your bundles require less bandwidth to fetch.
If you haven’t already, enable compression on the server-side as well.
Another great way to further reduce the size of your CSS — and markup— is obfuscating class names.
To achieve this, you have a couple of options based on your project setup:
Following these 10 simple steps will help you to write CSS files that are:
- more lightweight
- easier to maintain
- easier to scale
Not only that, but using utilities such as a predefined color palette or typography rules, will help you create more consistent designs. Your styles will also be more reusable, so you can save time on your next project.
What are some other CSS best practices you follow but were not mentioned in this article? Let us know in the comments!
Thanks for taking the time to read this article and happy styling!