21 ways to streamline your CSS

These days, CSS development is a complex process. You may be working on sites with large CSS files, multiple developers ,and long development timelines. The more complex your CSS files become, the more difficult it is to work with them. This article will present some tips and tricks for keeping your CSS files organized and easy to work with.

Things to keep in mind

Always remember that:

  • You may not be the only one who needs to work with this code. You may decide to distribute your Wordpress theme in the future. You may leave your job. You may pass the site on to another developer. Someone else needs to be able to work with your code.
  • Everyone has their own preferences. That doesn’t mean that we can’t all follow some simple processes to make our code easier to work with.

Keeping your CSS organized

Note: the tips listed below are listed roughly in order of difficulty. Basic techniques are described first.

  1. Avoid using inline CSS or in-page CSS

    CSS can be applied to elements in three different ways:

    • inline (<p style="margin-left: 20px;")
    • on page (<style> block inside the page <head>)
    • imported using @import or

    Using imported CSS is the best way of keeping your CSS separate and easily maintainable. Only use inline CSS if you have no other choice, or it is a truly one-off situation that won’t be used elsewhere. On page CSS should only be used for properties that only apply to the current page. Even then, if there is a lot of CSS it’s best to create a new .css file and import it.

  2. Use classes and id’s where appropriate

    Remember the difference between a class and an id. An id is to be used only once on a page. If something occurs once and only once on a page, use an id. If it occurs multiple times, use a class. Also consider future changes to the site — ask yourself: is there any chance that I would want to repeat this style on the page? If the answer is yes or maybe, use a class.

  3. Use a consistent style

    You may choose to write your CSS inline, like this:

    p {font-size: 10px; margin-bottom: 1em;}

    Or in block format, like this:

    p {
      font-size: 10px;
      margin-bottom: 1em;
    }
    

    There are several variations of the block format, depending on where you put the opening { and whether the properties are indented or not. This is largely a matter of personal preference; some developers find that the inline method makes it easier to find selectors, while others find that the block method makes it easier to find properties. Choose a format and stick to it throughout your CSS file.

    If you encounter a CSS file that uses a different format from the one you prefer to use, you can use a CSS formatting tool to reformat it to suit your needs.

  4. Don’t specify the same selector more than once

    Poor organization or laziness may result in some selectors being specified more than once. For example, you may specify some properties for lists at the top of your stylesheet, then decide later on to add some additional properties. These new properties may get added in a new block at the bottom of the CSS file, rather than with the original selector earlier on.

    Before adding a selector — particularly a generic element selector — make sure to check through you CSS first to make sure it hasn’t already been used.

  5. Use lower case selectors only

    Selectors are case sensitive, meaning that #Content is not the same as #content. In order to avoid mistakes, it’s best to always specify selectors in lower case. It’s also helpful to be consistent about other characters used in your selectors, e.g. use only underscores or dashes, not both.

  6. Use standard conventions for common ids

    Web designers have come to an informal consensus about how to name certain elements. The header is called #header, the footer is called #footer, and the main menu is #nav or #navbar. There is some variation about container elements (#container, #wrapper etc.). It’s best to follow what others are doing, rather than inventing your own names. Sticking to conventions means other developers will be able to understand your code.

  7. Use meaningful selector names

    Whenever possible you should choose semantic (or meaningful), names for your selectors. Other developers should be able to tell by reading your CSS what the selectors are for.

    In addition, class names should be able to account for changes in design. For example, if you decide to change that red text to orange, you shouldn’t have to change the name of the class as well. Instead, think about why that text is red. Is it because it’s important? Good, then call it .important.

    The only time when you would use presentational names is when there really is no logical reason why this element is styled the way it is. For example, if you have a class that aligns a photo to the left, there is no more meaningful way to label it than .photo-left (or .imgleft, or .figure-left, or whatever you prefer).

    This is also a matter of balancing meaningfulness with clarity. There may be a tendency to get too strict about semantics, to the point where people don’t understand your code anymore. For example, the id "footer" really describes the location on the page. To be more semantic, you could call this "site-meta" or something like that. However, in reality "footer" is a much clearer label.

  8. Use shorthand wherever possible

    Instead of:

    ul {
      margin-left: 20px;
      margin-top: 10px;
      margin-bottom: 10px;
    }
    

    use:

    ul {
      margin: 10px 0 10px 20px;
    }
    

    For margins and padding, the order is always top, right, bottom, left. You can further this shorthand by dropping the bottom and left values if they are the same as top and right. For example:

    p {
      margin: 6px 0;
    }
    

    is the same as:

    p {
      margin: 6px 0 6px 0;
    }
    

    Webcredible has a good CSS shorthand reference.

  9. Order properties within a selector

    If a selector has a lot of properties it helps to keep them ordered in some way. Some designers prefer to sort them alphabetically, like this:

    ul#navbar {
      background-color: #600;
      color: #fff;
      font-size: 12px;
      height: 24px;
      margin: 90px auto 0;
      padding: 0;
      text-align: right;
      width: 768px;
    }
    

    Personally, I like to sort things by purpose (see how height and width aren’t placed together in the above example?). Colours and backgrounds go together (color, background color, background image), box model properties go together (height, width, margin, padding, position etc.), text properties go together (font, text-align, line-height etc.). It might look like this:

    ul#navbar {
      width: 768px;
      height: 24px;
      padding: 0;
      margin: 90px auto 0;
    
      text-align: right;
      font-size: 12px;
    
      background-color: #600;
      color: #fff;
    }
    
  10. Use a CSS reset

    A CSS reset declaration overrides all of the browser’s default settings. All browsers come with default stylesheets that control how basic elements look. Paragraphs have margins. Unordered lists have round bullets and a left margin.

    Usually, designers will want to override most of these values. Instead of individually overriding every setting you want to change, it’s often best to just wipe the slate clean and start over.

    Eric Meyer has developed a good CSS reset that you can copy and paste into your CSS file.

  11. Divide your CSS file into sections for particular tasks

    Useful common classes

    There are several common classes that I usually like to include in my stylesheets. They include:

    .important

    .fineprint

    .photo (or .thumb)

    .photo-left

    .photo-right

    .caption

    .update and/or .correction (for a blog)

    Arranging selectors into groups for different purposes helps to keep things together. For example, it wouldn’t make sense if the ul selector was on line 25 while the li selector was on line 164. Keeping them together will ensure that you see related selectors and ensure that you don’t accidentally call a selector more than once.

    This is how I like to do mine:

    1. CSS Reset
    2. Basic elements (body, paragraphs, lists etc.)
    3. Commonly used classes (these are things that I might need to reference frequently, such as classes that align images to the left or right)
    4. Specific selectors for certain parts of pages (e.g. A special section of one page that creates a block around some text and an image)
    5. Template layout:
      1. containers
      2. header
      3. navigation
      4. content
      5. footer

    Inside these groups, similar items are grouped together as well. For example, all list related selectors would be put together in section #2. Higher level selectors go first, so ul would precede li.

    The reason I organize it in this way is mainly to support the CSS cascade but also for accessibility. The CSS reset and basic elements need to go first so they can be overridden later by more specific selectors. After that, I need to find those common classes and elements more frequently, while the template layout rarely changes.

  12. Add a header for each section

    Many developers have a favourite way of marking sections in their CSS, such as:

    /* ------------ common classes ------------ */

    /*======= common classes ====== */

    /* ----------------------------------------- common classes */

    This makes it easy to find elements you need to work on. The style you choose for these headings is up to you, just be consistent about which format you use.

  13. Include a colour reference

    How many times have you gone hunting for the correct hex value for the colours used in your design? Specifying the colours at the top make them easy to access. All you need to do is scroll to the top and copy and paste. It might look like this:

    /*
    Main medium green: #d7ecaa
    Lighter green: #f1fcdb
    Very light green: #e8f7c4
    Medium brown: #a66c38
    
    Lighter brown: #632f00
    */
    
  14. Otherwise, use comments only when necessary

    If you write your CSS well there should be little need to explain what you’re doing. Any designer who understands CSS will understand how and why you’ve used certain properties. Extra comments clutter the stylesheet and increase the file size. The only exception to this would be cases where something you’ve done really doesn’t make sense. For example, you had to include an extra property to correct a display problem in a particular browser.

  15. Consider dividing your CSS into separate files

    If you have very large CSS files, it might be worthwhile to separate it into two or more different files. This way you can use different files for particular tasks. I often separate the template layout into a different file since it doesn’t change very much after the initial site launch. The CSS reset could also go into a separate file. In addition, you could create separate files for large sections of CSS used only on certain pages, such as forms. This way all pages won’t be loading code that is only used on a few pages.

    Your list of CSS files might look like this:

    1. reset.css
    2. content.css
    3. layout.css
    4. forms.css

    Ensure @import declarations are written in the correct order, so that they cascade correctly.

  16. Avoid using browser specific hacks

    There are many ways to target particular browsers with CSS (see Web Devout for some examples). These usually involve exploiting bugs in a browser’s rendering engine which cause it to ignore certain selectors or groups of characters.

    The first problem is these hacks are not usually documented very well. Months or years later you may not remember why that voice-family property was there. Secondly, future versions of the browser being targeted may correct the very problem you are exploiting. This is fine if they have also corrected the bug, but what if they haven’t?

    If you learn to write CSS well there shouldn’t be much of a need for hacks. I find that there’s usually a good method of solving the problem for standards-compliant browsers. However, Internet Explorer is often an exception.

  17. Target IE using conditional comments

    Internet Explorer’s conditional comments make it easy to add code that can only been seen by IE. Not only that, but you can target specific versions or ranges of versions, anything less than IE 6 for example.

    There are two ways to serve different CSS to IE using conditional comments. The first is to simply insert a different CSS file for IE:

    For all versions of IE:

    <!--[if IE]>
    <link rel="stylesheet" href="ie.css" type="text/css" />
    <![endif]-->
    

    For versions less than and including than IE 6:

    <!--[if lte IE 6]>
    <link rel="stylesheet" href="ie6bugs.css" type="text/css" />
    <![endif]-->
    

    For versions less than (and not including) IE 6:

    <!--[if lt IE 6]>
    <link rel="stylesheet" href="ie5bugs.css" type="text/css" />
    <![endif]-->
    

    However, some designers believe that this is a problem because it separates the IE-only CSS from the rest. When making a change to the regular stylesheet you may not realize that the same element is also adjusted in the IE-only stylesheet. Instead, you could add a containing DIV around your page with an IE-only id.

    After the body tag put:

    <!--[if IE]>
    <div id=”ieroot”>
    <![endif]-->
    

    And don’t forget to close it at the bottom:

    <!--[if IE]>
    </div>
    <![endif]-->
    

    Using this technique, you simply use your #IERoot selector in your regular CSS file to add extra rules for IE only. This way you can keep the special IE-only CSS together with the main CSS for that selector.

    Remember: any code targeted to IE only should only be used when the fix breaks the layout in other browsers. Otherwise, there’s nothing wrong with including a few extra properties if they have no effect on other browsers.

    Some more advanced conditional comment techniques are described in Supporting IE with conditional comments at Dev.Opera.

  18. Use minimal specificity

    In CSS, more specific selectors will override more general selectors. Let’s say we want to add some padding to list items. We could do it like this:

    div#wrapper ul li {
       padding: 4px 0;
    }
    

    If #wrapper is a containing div for the whole page, all lists will have 4px top and bottom padding. Now, what if I wanted lists inside the #content div to have less padding. I would have to do something like this:

    div#content ul li {
       padding: 2px 0;
    }
    

    You can see how this leads to more and more complex selectors over time. The more selectors you add, the more you need to include to override those properties later on. In order to avoid this problem it’s best to minimize the specificity of your selectors (use as few selectors as possible). Instead of the above I could have simply done this:

    li {
      padding: 4px 0;
    }
    
    #content li {
      padding: 2px 0;
    }
    

    For more information on how specificity is calculated, try Specifics on CSS Specificity from CSS tricks.

  19. Make full use of CSS selectors

    You don’t have to put a class or id on every element you want to style differently. Instead, learn about all the different CSS selectors available to you. You could, for example, create a navigation menu like this:

    <div id="navbar">
       <ul>
       <li class="navitem"><a href="somewhere.html" class="navlink">link 1</a></li>
       <li class="navitem"><a href="somewhere2.html" class="navlink">link 2</a></li>
       <li class="navitem"><a href="somewhere3.html" class="navlink">link 3</a></li>
       </ul>
    </div>
    

    Your CSS could look like this:

    #navbar ul {
      margin: 0;
      display: inline; 
    }
    
    #navbar .navitem {
      float: left; 
    }
    
    #navbar .navitem a.navlink {  
      color: #fff;   
      background-color: #600; 
      text-decoration: none;
      padding: 2px 10px;
    }
    
    
    #navbar .navitem a.navlink:hover {
      background-color: #666;
    }
    

    The main problem with this is that you end up with a lot of extra classes in your html that really don’t need to be there. Instead, you could simply use descendent selectors to apply some CSS to the list items inside the navbar div. While we’re at it, we don’t really need that div either. Instead, we can apply the id to the ul instead:

    <ul id="navbar">
       <li><a href="somewhere.html">link 1</a></li>
       <li><a href="somewhere2.html">link 2</a></li>
       <li><a href="somewhere3.html">link 3</a></li>
    </ul>
    

    Your CSS could look like this:

    #navbar ul {
      margin: 0;
      display: inline;
    }
       
    #navbar li { 
      float: left;
    }
       
    #navbar a {
      color: #fff;
      background-color: #600;
      text-decoration: none;
      padding: 2px 10px;
    }
    
    #navbar a:hover {
       background-color: #666;
    }
    

    This results in much cleaner and simpler HTML and CSS.

    Roger Johansson has an excellent series of articles on CSS selectors:

    Part 1 – universal, type, id, and class selectors

    Part 2 – combinators, combined selectors, grouping, and attribute selectors

    Part 3 – pseudo-classes and pseudo-elements

    Remember that not all selectors are supported in all browsers. Check this handy reference chart to make sure the selectors you want to use are supported in most browsers. Less supported selectors can also be used in combination with the progressive enhancement techniques described below.

  20. Consider progressive enhancement

    With progressive enhancement you can take advantage of newer standards while still presenting an attractive and usable interface to older browsers. Newer CSS properties and selectors are used for optional design elements, such as creating rounded corners.

    Instead of creating multple nested divs with background images to create rounded corners, you could simply use the -moz-border-radius and -webkit-border-radius properties to create rounded corners in Firefox (using the mozilla/gecko rendering engine) and Safari (using the webkit rendering engine):

    #mydiv {
      -moz-border-radius: 10px;
      -webkit-border-radius: 10px;
    }
    

    With techniques like this you can create additional effects and take advantage of new CSS without writing a lot of extra code or degrading the experience in older browsers. That’s why it’s called progressive enhancement!

  21. Redundancy or Dependency?

    If you’ve been writing CSS for awhile you’ve probably come across this problem. It’s normal to have a lot of elements with similar propertes. After all, visual consistency is one of the keys to a good design. The problem is that you may end up writing that same set of properties repeatedly throughout your CSS.

    An alternative would be to break out these common groups into their own classes or use grouped selectors to apply a generic set of properties. This class would then be applied to any elements that require them. But wait – what if you want to modify one of the properties applied to one of these elements? Now you need to add a more specific selector to get the element you need.

    If you continue following this method you may end up with a lot of selectors applying CSS to the same element. Changing one property may have unforseen consequences to other parts of the design.

    Wouldn’t it be easier to separate the CSS properties for each selector? But now we’re back to where we were in the beginning, rewriting the same CSS multiple times.

    This, again, is a matter of personal preference. Experiment with both methods and see which one works best for you. Redundancy often works fine for smaller projects while larger, more complex projects benefit from the dependency approach.

    An in-depth explanation of this concept can be found in Redundancy vs. Dependency from Dave Shea.

References

Discussion

Discuss this article on the forums.

Megan McDermott's picture

About the Author

Megan is co-founder and editor of A Padded Cell and administrator at The Webmaster Forums. She has been designing websites since 1997, with expertise in design, information architecture, usability, HTML/CSS, Drupal theming, and more. Megan is also a partner and co-founder of Woolwich Web Works: A small team that can do big things!