Guidelines for better and faster CSS

Gone are the days when we used to write arbitrary CSS without considering much about its structure. As developing web applications is becoming more and more common it’s important to organize CSS in proper way. Organising CSS is not only beneficial for rest of the team but it can also significantly impact the performance of your web application. CSS of a web application can go well beyond 10k lines, in such scenarios it becomes difficult not only to manage but also to scale the code without breaking any other components of the page. Philip Walton said on the architecture of CSS [1] 

Goals of a good CSS architecture shouldn’t be that different from the goals of all good software development. CSS should be predictable, reusable, maintainable and scalable.


Output of CSS should be predictable. While working with teams, regression happens all the time. Especially in CSS where architecture is not properly defined then one minor change can bring undesirable effects by breaking up the components from other pages.


Reusability is the essential part of software development. Whether it is Object Oriented Framework or MVC, reusability or ‘Do not Repeat Yourself’ is an essential part of Programming Architecture. It also applies for CSS. Rules should be defined in such a way that they should be reusable. It also helps to reduce development time and brings consistency to User Interface design of the application.


Updating the CSS can also bring hassle. By updating one rule can break another component. It should not happen in a proper architecture.


It should not matter if development team consists of a single person or large team, adding new rules should not bring regression. Architecture of stylesheet should look so obvious that any one should be able extend the code without going through reading documentation.

People often complain that it’s easy to go through thick Computer Science books and talk about good programming practises which are never implemented in the real world. But there are some popular open source projects like jQuery UI, Twitter Bootstrap or WordPress[2] which follow these practises.

Object Oriented CSS

Object Oriented Principles consist of abstraction, encapsulation, inheritance, polymorphism and reusability. All these principles can also be applied to CSS. While defining the rules one should always make sure that skin and layout should not be come together. There should be separate classes for skin and layout, if it is followed then it becomes easier to extend and maintain styles.

.button {
  font-size: 1.125em;

  border: none;
  border-radius: 1.25em;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  outline: none;

  vertical-align: middle;
  display: inline-block;
  padding: 8px 16px;
  margin: 1.5em 0;

.button-primary {
  background-image: -webkit-linear-gradient(top, #F1394C 5%, #BC3135 100%);
  background-image: -moz-linear-gradient(top, #F1394C 5%, #BC3135 100%);
  background-image: -ms-linear-gradient(top, #F1394C 5%, #BC3135 100%);
  background-image: -o-linear-gradient(top, #F1394C 5%, #BC3135 100%);
  background-image: linear-gradient(top, #F1394C 5%, #BC3135 100%);
  background-color: #F1394C;

  border-bottom: 1px solid #2A0E00;
  color: #FFCCCC;

.button-large {
  font-size: 1.5em;
  padding: 12px 20px;

Subsequent HTML for implementation of classes will look like

<!-- Standard Button -->
<a class="button button-primary" href="#">Standard Button</a>
<!-- Large Button extended from Standard Button-->
<a class="button button-primary button-large" href="#">Large Button</a>

As you can see above, layout related rules are mentioned in .button class while skin related rules are mentioned in .button-primary. Due to this reason it becomes easier to extend the .button. If one decides to add a different color for the button then there will be a separate class with a different color scheme by keeping base rules such as padding, margin, alignment, etc. unchanged. If one decides to add larger or smaller button then existing rules such as font-size, padding can be overridden and inherit the rest of the rules. 

Such approach makes sure that buttons used in whole application will be consistent with the design as well as easier to extend which can prevent regression.

Modularity and Compartmentalization

There can not be a worse nightmare than finding rules for a selector, scattered in a file with 20k lines of code. As code base grows it is essential to compartmentalize the rules depending upon which components it is dealing with. Jonathan Snook has provided a really nice solution for modularity in his book Scalable and Modular Architecture of CSS (SMACSS)[3]. He proposed to divide code in five components viz base, layout, modules, state and theme. But maintaining five different components can also lead to confusion especially among large teams. I reduced them to four components.


It will be a collection of base rules for elements such as body, headers, input, paragraph etc. These rules won’t change much. Following example can provide broader perspective-

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
body {
  font-family: Helvetica, Arial, sans-serif;
  font-weight: 200;
  font-size: 16px;
  background-color: #FCFCFC;
  color: #58585b;

  margin: 0;
  padding: 0;
h1 { font-size: 2.25em; }
h2 { font-size: 1.5em; }
h3 { font-size: 1.125em; }
h4 { font-size: 0.875em;  }

pre {
  font: 0.75em Monaco, monospace;
  line-height: 1.5;
  margin-bottom: 1.5em;
code {
  font: 0.75em Monaco, monospace;
p {
  margin: 4px 0 12px 0;
a, a:visited, a:link {
  color: rgb(0, 173, 255);
  text-decoration: none;
a:hover, a:active {
  color: rgb(0, 143, 255);
  text-decoration: none;


Collection of rules dealing with the layout and structure of sections. It can involve margin, dimensions. It should not involve anything related to colours, fonts, decoration; strictly layout only. In case of grid, layout should look like following example

.grid {
  display: table;
  margin: 10px;
  padding: 5px;
.grid-column {
  float: left;
  padding: 5px;
.grid-column-4 {
  width: 200px;
.grid-column-5 {
  width: 175px;


Collection of rules which decide color, font, shadows etc. of the element. It specifically deals with how a module will look like. Above example of grids can look like

.grid {
  overflow: auto;
.grid-white {
  -webkit-box-shadow: 0 -1px 0 #FF9999;
  -moz-box-shadow: 0 -1px 0 #FF9999;
  -o-box-shadow: 0 -1px 0 #FF9999;
  -ms-box-shadow: 0 -1px 0 #FF9999;
  box-shadow: 0 -1px 0 #FF9999;

  background-color: #F1394C;
  border-bottom: 1px solid #2A0E00;
  color: #FFCCCC;


These rules will be usually implemented in JavaScript. It can include rules related to state, visibility, animation etc. e.g.

.hide {
  display: hide;
.animate {
  -webkit-transition: 0.3s all ease-out;
  -moz-transition: 0.3s all ease-out;
  -o-transition: 0.3s all ease-out;
  transition: 0.3s all ease-out;
.fadein {
  visibility: visible;
  opacity: 1;
.fadeout {
  visibility: hidden;
  opacity: 0.9;

Minimised Specificity

Before moving to specificity, it is important to understand how browser works[4]. Understanding how DOM construction and painting is done by browser can help us to create a better structure for code base. It will also be helpful to do optimizations.

Rendering workflow of a webkit browser

Rendering workflow of a webkit browser (Courtesy-HTML5 Rocks)

As shown in diagram, HTML and CSS parser takes care of parsing and validating corresponding HTML and CSS. While each node of the render tree is being constructed, rendering engine (in this case webkit) goes through all the parsed stylesheet every time to create a node i.e. if there are nodes then rendering engine goes through whole stylesheet times to implement proper rules for respective node. Of course there are optimizations performed internally which may vary browser to browser but in layman terms this is how render tree is constructed. Due to the fact that browsers go through style rules every time, they match selectors from right to left[5].

Right to Left Selector Matching Flowchart

Right to Left Selector Matching Flowchart

As shown above rendering engine goes through all the rules for each node construction. It first checks if the key selector (i.e. extreme right selector) matches with current node or not? If it is matched then it goes to adjacent selector to check if it is the parent of the current node. If any of the condition returns false then rendering engine moves to next rule otherwise the current rule is applied to the node. Hence the more number of adjacent selectors or in other words more the level of specificity  more time it will take to complete the process.

Once the render tree is constructed, it is further sent for painting and eventually dumped on the screen. This process is not a onload process. It happens all the time. When you add/remove elements in the DOM Tree dynamically or add/remove certain set of rules, painting and reconstructing of tree happens on such occasions. In case of single page application frequency of painting and reconstruction increases even more as components like modals, alerts, containers are generated dynamically.

Having just one level specificity is desired approach but 3 level specificity is also acceptable. Because sometimes it becomes cumbersome to manage 1 level specificity.

body .container div span a {
  /* BAD Approach */
.container-link {
  /* Correct Approach */

In case of ID, its important to have only one level specificity. IDs are suppose to unique in the document hence there is no need to mention parent selectors.

.container #special-element {
  /* BAD Approach */
#special-element {
  /* Correct Approach */

Use Classes

There are four types of selectors

  1. ID Selector
  2. Class Selector
  3. Element Type Selector
  4. Universal Selector

According to the W3 Spec[6] an ID Selector should be unique in the document. Being unique in the document, ID selector is the most fastest selector. As long as reusability is concerned ID prevents us from doing it. Having poor naming conventions can lead us to add duplicate IDs which browser fixes internally.

A selector which comes most close to Object Oriented CSS is Class Selector. If proper modularity and naming conventions are applied then every class can be reused. Class selector is second fastest to ID but it is the most effective way to organize your code.

Considering how browsers work, having Element Selector is not a good idea. Every time when a node matches definition with element type, rendering engine is going to stop at that rule and start iterating over adjacent selectors. Consider that there are 100 divs present in a DOM and a style rule has div as key selector then every time a div node is being constructed, rendering engine will halt at the rule with div being key selector, which is waste of time.

The last thing you want in a document is Universal Selector. If there is no strong reason to have Universal Selector, it should not be added in the document. It is the most expensive selector. Suppose there are nodes present in the document then rendering engine will go through the rules consisting Universal Selector times.

Considering all the scenarios, it might look good to use ID as it is the fastest selector. But ID will prevent us from implementing Object Oriented Paradigms. ID selectors should be used for JavaScript only. Using class selectors in CSS will be helpful to maintain and scale the stylesheet which we discussed above.

Naming Conventions

Naming convention plays important part to implement reusability and minimized specificity. If meaningful and unique names are given to selectors then minimized specificity and reusability can be achieved. It must have happened numerous time that duplicate names are assigned to a class or worst case to ids e.g. #title, #container etcThis problem can be solved by having namespacing of elements in the name itself. Having hierarchy of nodes in the name will not only make it unique but also meaningful. Consider an example of gallery below –

.gallery { /* Rules for gallery */ }
.gallery-montage { /* Rules for container */ }
.gallery-montage-title { /* Rules for title */ }
.gallery-montage-thumbnail { /* Rules for thumbnail */ }

It is not necessary to have really big hierarchy in name itself, it should be according to your convenience but at most 3 level hierarchy seems acceptable. Namespaced names helps to give idea about that node in just a glance and it also helps to achieve unique naming. It’s better to have long names rather than having long specificity. Such practise is beautifully implemented in jQuery UI CSS. I recommend to go through jQuery UI to see it in action.

Compress, Sprite and Font Icons

These are the most common optimization techniques recommended. There are some several popular articles on explaining several ways and tools for compression[7]. I won’t go in much detail of this process.


In order to take less time to load content from network, gzip compression recommended. All the content which is supposed to be served should be gzipped on the server. It is an effective and common practise to reduce loading time. Image compression can also reduce size of the image substantially. Some of the popular tools which I use for image compressions are and ImageOptim. There is also a way to compress JavaScript and CSS files. Tools like Google Closure Complier, YUI Compressor can reduce size of your project files. They are capable of eliminating dead code, remove empty spaces, comments and convert it to reduced files. An open source project,; curated by Paul Irish and Addy Osmani is capable of doing all these compressions with one command. That tool is specially designed for managing web applications and compression technique is one of the main feature.

Image Sprites

Instead of loading hundreds of images, just load one image which consists of sprite or mosaic of required hundred images and use background-position property to render them on the screen. When I came across this technique I was completely jaw dropped. Glue is one tool for generating image sprites and corresponding CSS. This technique can reduce bandwidth substantially.

Font Icons

Font Icons can be alternative to image sprites. All the common iconset such as Social Media, Toolbar can be used via Font. Advantage of using fonts is that it will not only render well on retina display but you can also alter its dimensions and color using CSS properties. Font Icons are also useful if your webpage follows flat design. This technique was made popular by GitHub’s Octicons[8]. Some popular ways to create font icons are Font Awesome and Fontello or you can create your own fonts using tools like Adobe Illustrator.

As far as compression and optimization techniques are concerned Google Chrome’s Developer Tools come to rescue. By doing ‘Audit’ of your website via DevTools, you can get a list of optimizations you are supposed to perform. Just open DevTools, click on Audit tab and Hit Run.

DevTools in action

DevTools in action

Enable CSSLint

There had been some speculation whether to use CSSLint or not[9]. It is sometimes annoying. Even CSSLint’s webpage says

CSSLint will hurt your feelings*

But I recommend you to use it. It helps you to fix your rules. Before CSSLint I was not aware that in case of display:table-cell, there is no need to add margin property. I used to ignore it because code just worked. CSSLint can help you to figure out such numerous problems. However CSSLint throws warning on certain conditions which may not sound right to you. These conditions incluse use of IDs, styles for header tags, ignorance of box-model etc. But you can always ignore these warnings (after all warnings are there to ignore ;)).

Best way to use CSSLint will be to install CSSLint plugin/extension for your text editor. I use Sublime Text, it has a great package called ‘SublimeLinter‘ which comes with linters for almost all popular languages. In case of Sublime Text, you will need to install CSSLint via Node Package Manager. Once you have CSSLint, you can disable certain rules in Sublime Linter Preferences. Here are my preferences-

        "adjoining-classes": "warning",
        "box-model": false,
        "box-sizing": false,
        "compatible-vendor-prefixes": "warning",
        "display-property-grouping": true,
        "duplicate-background-images": "warning",
        "duplicate-properties": true,
        "empty-rules": true,
        "errors": true,
        "fallback-colors": "warning",
        "floats": "warning",
        "font-faces": "warning",
        "font-sizes": "warning",
        "gradients": false,
        "ids": false,
        "import": "warning",
        "important": "warning",
        "known-properties": true,
        "outline-none": "warning",
        "overqualified-elements": "warning",
        "qualified-headings": "warning",
        "regex-selectors": "warning",
        "rules-count": "warning",
        "shorthand": "warning",
        "star-property-hack": "warning",
        "text-indent": "warning",
        "underscore-property-hack": "warning",
        "unique-headings": "warning",
        "universal-selector": "warning",
        "vendor-prefix": true,
        "zero-units": "warning"

I hope this guide was helpful for you. If you have any questions or if you find any bugs in this article, feel free to add a comment below.


  1. CSS Architecture by Philip Walton
  2. CSS source code/architectures of jQuery UITwitter BootsrapWordPress
  3. Scalable and Modular Architecture for CSS by Jonathan Snook
  4. How Browsers Work by Tali Garsiel & Paul Irish
  5. Why do browsers match CSS selectors from right to left? – Stackoverflow
  6. Global structure of an HTML document by W3.Org
  7. Best Practises for Speeding up your Website by Yahoo Developers Network
  8. Making of Octicons by Github
  9. CSSLint on Hacker News

Express your thoughts

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s