How to structure large CSS files

Many methods exist to structure your CSS. This article tries to describe the method I use. I call it the “Tree method”, since it structures the CSS like… that’s right, a tree structure. I want to stress that it isn’t my invention; I just describe and give reasons for its rules.

Everyone that has built a bigger site has had to deal with the mess CSS so easily become. There are ids and classes all over the place, and to find where a certain class is defined you usually need to use some search feature in your editor. Matching the other way, from the CSS to the HTML is even harder; you don’t even know what file a certain class is defined in. It’s a mess.

The Tree method tries to structure the CSS into logical blocks; blocks taken from the HTML. It also aims to be easy to understand for anyone. No secret codes or difficult ordering schemes.

Order your selectors like the HTML

One of the problems of mapping between the HTML and the CSS is that they usually differ in structure. The HTML is (if you’re lucky) structured like a convenient semantical tree while the CSS often is ordered by something random like fonts, colors, and positioning.

To make moving between the two worlds easier we want to make them as similar as possible. Is the HTML divided into header, content, and footer? Then make sure that’s the three major parts of your CSS as well. Have you put the navigation above your header in the HTML? Then order it like that in the CSS as well! Any other structure makes moving from the HTML to the CSS much harder. You might be able to find all font manipulations in one part of the CSS, but only if you know that this particular developer uses that exact scheme. No, let’s keep it simple.

Here’s a simple example where we just order the selectors:

#header { ... }
h1 { ... }
h2 { ... }
#content { ... }
p { ... }
em { ... }
strong { ... }

When grouping several styles into one definition I just put the group above both of their specific styles. #header, #content comes before both #header and #content.

Always use the “full path” to elements

The above is very easy to get an overview of, but the experienced developer knows that very few sites are that easy. Something you often want is a way to define different styles to different parts of a page. Let’s say you want green links in the navigation, but want to keep them blue everywhere else.

For this we use sub selectors. The selector #navigation a lets you give all links inside your navigation another look. But let’s take that further. Why not always write the full path to your elements? Why not use #navigation ul li a instead? Doing this gives a developer looking at your code a lot of information about how the HTML and CSS belongs together.

Lets add that to the previous example:

#header { ... }
#header h1 { ... }
#header h2 { ... }
#content { ... }
#content p { ... }
#content p em { ... }
#content p strong { ... }

This does change the meaning from before. Before we selected all the level two headers; now we only select headers inside of the header division. Extending each selector with a “path” has made our CSS rules more specific, and specific means more control for you.

This also makes for fewer new ids and classes; just specify the path to an element instead of adding a class for it. Don’t add a new class or id unless you really need to.

We still have the issue of “common styles”; styles that we want to apply to elements in different parts of the tree. Since they should be applied to all elements they don’t fit in the tree structure we’ve built. Instead we make a section in the beginning of the file (or a separate) with just “general styles”. Don’t add rules to this section if you only use them once in the document, you want as much of your code to be in “the tree” as possible.

Indent your code cleverly

To make the code even easier to understand I always add indentation (for those that don’t know that word: it means spacing in front of blocks of text). Indenting makes the tree structure we’re trying to build even clearer, you can easily find the major sections and dig down from there.

Lets add indention to you our example too:

#header { ... }
   #header h1 { ... }
   #header h2 { ... }
#content { ... }
   #content p { ... }
      #content p em { ... }
      #content p strong { ... }

Don’t take indentation too far. If you’re styling tables and using thead in the markup, but don’t change the style of it, you can skip that indentation level. Double indention just for the sake of it is just a waste of space.

Special case: Templating

We also need to deal with rules that only appear on some of our pages. Perhaps we want the home page to look somewhat different than the sub pages? We solve this by giving an id or class to the body element. Doing this lets me specify styles for just one specific page, and setting the id or class on body makes me able to change anything in the document based on that.

These page specific styles need a place in the tree too. Here I tend to break from the above scheme and put them together with the style they change. So body#page_home #header h1 is one step below #header h1 in the tree. That makes it easier to see all styles for a certain element, instead of scrolling back and fourth (like you need to do if you don’t remember your general styles). Keep your templates together with the style they change instead of completely separate.

If you want bigger changes, perhaps a totally different look on some pages, there’s no reason to group things according to the scheme above. Move them to a separate file instead.

Each declaration on its own line

Indentation combined with full paths makes some lines rather long. This means that putting all declarations on one line will force you to scroll horizontally, something we already avoid on our sites. The simplest way to prevent horizontal scrolling is to use one declaration per line, so that’s what the tree method uses.

… in alphabetic order

Grouping of properties is another issue. I’ve seen grouping schemes based on all sorts of things; from splitting things into “positioning”, colors, and fonts, to people adding their properties completely randomly. I’ve chosen to just order them alphabetically. It’s one of the few methods that bring some order while still being simple enough. I’ve seen total beginners do this by themselves; something I believe is a good argument for it. It’s intuitive.

A simple example to illustrate:

#content {
  color: Blue;
  font: 3.4em Arial, sans-serif;
  margin: 0.5em;
}

One complaint I’ve heard on this method is that it splits up things that belong together. People tend to keep position: absolute and left: 0 together, just to name one such pairing. It annoyed me at first too, but declaration blocks rarely contain more than 10 declarations, and the alphabetic order still makes them easy to find. Also, why handle position different than float and margin?

 

That’s it! By following a few simple rules you can get a CSS-file that’s easier to overview, a file that you proudly can give away to the next developer. I can praise its existence all day, but you’re the judge of whether it works or not. Why not give it a try in your next project?

[Update: Maurice van Creij writes in and says that he’s using the same method. A good way to get started is to generate a CSS file from the HTML. He has written a javascript that does just that. Nice! Try generating a CSS file.]

[Update: Another part structuring your CSS is making sure you don’t load too much. I wrote an article previously about combining static and dynamic CSS.]

[Update: This article got digged to the frontpage. There’s a lot of good comments there (but as usual pretty harsh language).]

97 responses to “How to structure large CSS files

  1. A note, this site does not use this method (yet). If you want to see it in action, have a look at the KTH site I coded earlier this year. Since it’s a real world project it isn’t perfect, but it should give you an idea of how the method works.

  2. I structure the CSS this way:

    First I add all usual markup. Like removing margin and padding from all elements, removing borders from images and so on. Standard indentations for lists are (re-)set here as well.

    Second, there are all the layout-relevant divs (#content, #menu), ordered by appearance on screen, so header comes before content etc.

    Third there ist the content markup. I may repeat #content itself, but this time it’d be for some standard styling. Ordinarily, I just put all the

    #content p em

    -like stuff in this second part of the code. The headings first, then paragraphs, lists etc., then some special containers like the options for blogposts which show the amount of comments, or the author or so.

    Your method sounds nice as well. But what’s with large documents? I think it’s hard to indent nested layouts very well. If the layout is centered, split and whatnot, you got two or three levels for nothing but a div at the beginning.
    But the structure sounds like it’s maing sense.

    So, what do you suggest for the CSS markup “content”?
    Do you put float, margin, width etc. above font and border?

  3. @Christian Tietze: Interesting to hear! You probably have to give me that explanation in a comment for me to understand it :)

    I don’t think large documents is such a big issue. Selectors are a small part of the code, the declarations take much more space. As for wrapper divs I don’t indent them, like you say it feels like a mess, and it won’t confuse anyone that I don’t.

    My suggestions for declarations are at the bottom :) one per line and in alphabetic order.

  4. Interesting indeed. I however don’t really see the point with using “the whole path”, since it adds to the document size and doesn’t really give anything. I think a well structured (sematically ordered and correctly indented) document gives you enough info. Of course it’s a bit easier to read (especially for somebody who isn’t the original author), but with larger documents it can easily add up.
    Other than that i agree with everything you’re saying and actually do most of my css the same way.
    A new idea was to order the properties alphabetically. Could give it a try :)

  5. Interesting article! I also want to keep my CSS as tidy as possible and I’m following most of the methods you mention here, except for the alphabetic and indent methods which are really interesting by the way. I’m gonna try those at work tomorrow and see if it helps me.

  6. I agree with everything except “full path” selectors and alphabetic ordered declarations. Since the rules are indented you can tell where things belong anyway, and keeping selectors short and simple is good for performance (for what it’s worth).

    I don’t bother writing the declarations alphabetically. I usually don’t have a problem finding a specific declaration. Sorting them is extra work with little benefit.

  7. @Rowan Lewis: I personally enjoyed reading our Screen.css. My CSS files look even worse. Indentation seems to clear things up a bit. Or probably your CSS code is just too simple :D

    @Emil: What exactly do you want me to explain?

  8. @Kalle: good to hear, seems people are already using parts of the method.

    @Antti Kupila, zcorpan: full paths is really the most important of them. With large files you need to read 100 lines up to find the top parent to a rule. If you include the full path that info is on the same line. I find that I scroll back and fourth *a lot* less when using when using them.

    @Rowan: Nice! I’m just missing the full paths :)

    @Christian Tietze: I just mean that what you wrote in the comment here probably is needed in a commented section in the beginning of your CSS-file. I need to try and just give one of my files to see if they can handle it without instructions. I hope so!

  9. @Jens Wedin: Cool, although it doesn’t follow any of the five points I wrote about in the article, so I’m not sure how it’s a mix :)

    I’m sure yours works too though :)

  10. The order for CSS rules is roughly what Christian Tietze wrote: generic parts, single HTML selectors, layout divs and specific content. I like to set up the CSS so that identical styles are only defined once, like normalizing database tables. This may mean the order may need to differ.

    Property order is positioning, display, color, specific stuff (list properties, table rules), font and ends with box properties from the inside out: padding, border and margin.

    I recently changed from writing every property on it’s own line to combining them all on one line with the selector. I find that this gives me a better overview over the used selectors.

    To overrule some CSS on specific templates you can also include a second CSS file, called the same as the template it belongs to and override styles there.

  11. @Rob Schlüter: The problem with all advanced schemes like that is that they differ between developers. So when you open up a CSS file made by someone else you are utterly confused.

    I prefer to keep it simple.

  12. Great write-up. I write my code in a similar fashion, but without the indentation and alphabetical sorting. But I go one step further with ordering selectors by making comment headers to separate them. Probably overkill since it’s already easy to recognize a block of selectors. But I find it useful if I need to scan a file quickly.

  13. For the past month at work we have been developing conventions for our CSS. An idea we are using, which would extend your idea of ordering the selectors the same as the HTML, is to use @import to split the out major layout sections into their own files. For example, we have a stylesheet for the header, content, sidebar, and footer. Besides the benefit of finding rules easier, it also allows multiple people to work on different parts of the layout without stepping on each others toes.

  14. I have considered every one of your statements in the past. I have explored the potential of each rule, except the most obvious — alphabetize the declarations. Your argument works for me, that blocks contain at most 10 declarations. I used that argument to keep them out of order in favor of importance. After writing tens of stylesheets, alphabetical just makes more sense.

    Now that you’ve put these rules in print, I think it’s time I follow them rigorously. Thanks for the post.

  15. Pingback: Matt’s talking points » How to structure large CSS files (Yes, you do need to structure them)
  16. Whoever wrote this article should really think about using /*comments*/ as well.

  17. Pingback: meneame.net
  18. Using full paths in CSS selectors is not necessarily a good idea. This is because of specificity. The fuller the path, the more specific the rule and so the greater the importance applied to it.

    It’s generally better to be as concise as possible in selectors so that when you need to override a rule it’s fairly easy to be more specific.

  19. And anyone who puts declarations all one line is an idiot! That’s the most unreadable form of CSS. It should go without saying that each declaration should be a new line. Also, alternated selectors should be on a new line.

    e.g.

    a#link,
    a#visited {
      font-color: purple;
      text-decoration: none;
      padding: 0 0.3em;
    }
    
  20. Pingback: stuart @ amanzi » Blog Archive » links for 2006-11-26
  21. @John: Yes, this sites CSS is a mess (as I wrote in the first comment). It’s because it’s over a year old and I didn’t know this method then.

    @Seamus: Good idea. You could take it even further and make little modules with CSS rules that you only include if they are needed. I wrote about that some time ago in the article Static and dynamic CSS combined.

    @Paul: Good to hear. I don’t want to set hard rules you never should break, always adapt the rules to the situation at hand.

    @Kyle: Yes, I should have mentioned commenting as well, thanks.

    @Bruce Boughton: On the contrary. I’d say a bigger problem is when other rules collide with yours and you end up with unexpected behavior. Knowing about specificity is a must though, thanks for adding it.

    People that put everything on one line has their reason for it. If you want to call people idiot, please stick to digg.com :)

  22. Pingback: DLife » ???????CSS??
  23. Pingback: things to check out
  24. Like stated earlier using the /*Comment*/ within CSS is a better way to structure CSS then to just indent everything.

  25. “Always use full path to elements” – this is something I would disagree with. Such an approach is not a good idea, as the it leads you to use the maximum specificity for the rule’s selector straight away – this can lead to problems when you need to over-ride a general rule with a more specific one later on.

    p { attribute : value; }

    can be over-ridden by

    #content p { attribute : value2; }

    If you always use the ‘full path’ you can no longer over-ride a rule later in the document. You are ignoring the importance of the cascade and specificity by instructing people to ‘always’ use the full path. This is harmful to a proper understanding and use of CSS.

    Other than that, there are some good ideas here. Nice one. :)

  26. @Stuart: Why not do it *too*? I find that seeing the structure by looking at the code is better than having to read through documentation. Sure, comment when needed, but make sure it’s not needed that often.

    @Matt Wilcox: I don’t find that a problem. Since you’re adding rules at the most specific case (full paths), you only specify the style for that specific case. Why would you want to change that later on? The only case I see is when another “template” on your site wants to change it. That case is handled by using the suggested “body#template [full path]” trick, something that gives higher specificity and therefore works. Try it, it really works well.

  27. Pingback: Web Glad.Com » Blog Archive » How To Structure Large CSS files
  28. Great article Emil.

    I’m glad to see you advocate placing each declaration on a separate line. In Jonathan Snook’s recent post on the same topic he was in favor of placing all declarations on the same line, but to me, that way is a very difficult to interpret and maintain (even if it does make file sizes smaller).

    Indentation is something I’ve recently begun to do, and I find it greatly helps with readability.

    I’ll try your alphabetical suggestion on my next site…

  29. Pingback: Thinking Web (1) at houbi.com Blog
  30. Pingback: Web Links 11.26.2006 « Rhonda Tipton’s WebLog
  31. Pingback: Like Your Work » Blog Archive » links for 2006-11-27
  32. Pingback: Structure CSS Files| Baz Web Development: AJAX, Joomla, CSS
  33. Pingback: Jim O’Halloran’s Weblog » Blog Archive » links for 2006-11-27
  34. Pingback: links for 2006-11-27 « Sri’s Blog
  35. Pingback: links for 2006-11-27 at SridhaReena
  36. Pingback: Myglobalblog » Blog Archive » life is structuring large files
  37. I would advise against using the second one (“full path” to elements), as it means you can’t use CSS specificity to override your own rules in other files, or later on. In fact, I’d go as far as to say that you should always use the smallest path possible for a rule, and use classes where semantically appropriate. This means that you can easily override your rules later, with more specific ones.

  38. I cant stand indentation in anything but code. I hate HTML that is indented, maybe im still hardcore to the notepad days where if anything was indented it would go all off the side or when word-wrapped would be nasty mess.

    I also prefer no space after the colon :p

    ok that was anal-retentive but oh well :p

  39. @django forums: Nice to hear your opinion, I’m guessing you use an entirely different method to keep your CSS:es structured and organized. And of course that’s just fine :)

  40. A very good article As someone who routinely writes giant chunks of CSS, I can attest to the fact that these things work.
    I was never a big fan of alphabetizing properties – I always grouped “related” items – until I gave it a chance. Now, instead of having to jump around a list of properties (width and height may “jump up” in the order if position isn’t present) I can scan much more quickly.
    To join the battle on specificity, I’m with Emil: as specific as possible from the get-go. This doesn’t limit you from things like the cascade; rather, it lets you use the cascade to apply general properties to a large group of elements and very specific properties to very specific elements. I think specificity forces you to think about grouping and the cascade and helps reduce elements with duplicated or redundant properties, replacing them with elements gradually increasing in property specificity.

  41. @Adam McIntyre: Couldn’t agree with you more! Don’t miss Maurice’s script linked to at the end, if you use the same structure that I do it’s a big timesaver.

  42. Pingback: Algo que hacer - Weblog dedicado a la tecnología, Internet, libros, e-sociedad, hackers, marketing, curiosidades...
  43. Pingback: How to structure large CSS files - Electronic Communications and Marketing Strategies
  44. If you’re on Rails, you might like my css_dryer plugin which lets you nest selectors to avoid duplication. So:

    #header {
      h1 { ... }
      h2 {
        p { ... }
      }
    }
    

    becomes:

    #header { ... }
    #header h1 { ... }
    #header h2 { ... }
    #header h2 p { ... }
    
  45. @Andrew Stewart: very interesting Andrew! I think I like the different syntax you use, but it’s feels a little like a step backwards to the macro-age. It does become less typing on your part, but you miss important things (that are on your ToDo) like cachning. Good idea though.

  46. Pingback: How to structure large CSS files - Friendly Bit : Popular Bookmarks : eConsultant
  47. Pingback: How to structure large CSS files - Friendly Bit » the web hottest from slashdot, digg, reddit and del.icio.us
  48. Pingback: Optimus Pete » Blog Archive » CSS tips and articles
  49. Pingback: Urls Sinistras » Blog Archive » CSS
  50. Pingback: ASPECTO.Net - Notícias » Blog Archive » Estruturando o código CSS
  51. Pingback: refactor.it » Blog Archive » Strutturare i fogli di stile
  52. Pingback: My XHTML/CSS creation process | <img /> is Everything
  53. Pingback:   Some very useful links… by .: Jnbn :.
  54. Pingback: opendossier » Blog Archive » Always the same CSS question
  55. Pingback: My Hobby is Programming » Blog Archive » How to structure large CSS files (Yes, you do need to structure them)
  56. Pingback: Strutturare i CSS - ReFactor.it
  57. Another solution would be to break up the large CSS files into multiple CSS files. The top-level CSS file would have rules common to all pages. The other CSS files will either over-ride the rules of the main CSS file or define new ones.

    The problem is if you use server side includes (e.g. PHP) and have the page header (with the opening *and* closing HEAD tags ), you will include the exact same CSS files for every page.

    E.g. I include this on top of every page:

    
    
     CSS

    /* all css files included here */

    &lt;!-- menu -->
     &lt;a href="#" rel="nofollow"> Home &lt;/a>
     &lt;a href="#" rel="nofollow"> Other Page&lt;/a>

    That problem can be solved with a very messy and misguided solution – conditional if statements that test for the name of each page and include accordingly.

    The better way would be to use an MVC framework or plain Object Oriented PHP for a far more elegant solution.

  58. Pingback: Dan’s Test Blog » Blog Archive » How to structure large CSS files
  59. i’ve loosely based my latest project on andy budd’s (http://tinyurl.com/2oucvd) approach; splitting default, basic, links & navigation, layout, typography, colour, forms, and tables up into separate sections. obviously an alternative would be to source independent, dedicated, css files – this approach has never enticed me into using it. it’s just too fragmented imo, not to mention load time.

    one downside to splitting this info up into dedicated sections is you often find your self writing the selectors two or three times in different sections when you could, in theory, just include all properties under one selector in one place.

    breaking things up has far more benefits though. for instance you can sit down and concentrate specifically on the typography for instance (although in my next project i’ll be deciding upon my type before i do any layout). it’s far to easy to become a whore to type once the layout is all done and dusted.

    think i agree on the full path issue; i’ll be implementing that in my next project. look at it this way, if you do use full paths it ties in with the alphabetical approach nicely.

    not sure about the indentation thing, but nevertheless interesting. i’m one of those people that uses ‘the least human readable approach’, in one liners, for my css presentation. my justification is it’s less scrolling down to get to what you want; once there you can obvious format it how you like when/if editing it.

    i’m a big fan of CSS Formatter and Optimiser (http://tinyurl.com/2vpxfe) and use it at the end of every project to tidy things up, group selectors, shorten property values (hex colours, shorthand padding/margins etc) and generally get a nudge in the write direction for how i could make things a bit tighter in the next project.

    my 3 cents :)

    cheers emil!

  60. @Johaness: Yeah, if you look at a full site with lots of different subpages it gets more difficult, and I’ve often resorted to something like you describe. One CSS for global sites, and one for each subsection. I use server-side code to decide what to include when.

    @lewis litanzios: Great comment, thanks! I can see how people want to work with different sections at different times, but that’s not how I work. I always start with box layout, and then complete the same rules with typography information afterwards. Works well for me.

    I’ve actually never used a CSS Formater, but then again, I’m _very_ picky about what CSS i write, and it’s almost always already optimized when I first write it.

  61. ‘I’ve actually never used a CSS Formater, but then again, I’m very_ picky about what CSS i write, and it’s almost always already optimized when I first write it.’ – haha, i wish i could say i coded so neatly. workin’ on it as always. check it out and let me know if you find any of it useful.

    ‘I always start with box layout, and then complete the same rules with typography information afterwards.’ – so let me get this straight. you will have your universal h1, h2, h3… p typographical elements defined and then you’ll target h3’s and p’s (and whatever) in their native divs to give them extra styling, where appropriate?

    up until now i’ve really done my best to stick with my universal styles, but now i’m finding myself needing more than six-odd fonts per page, so am beginning to embrace semantic conventions e.g. a date font might be styled as .date{…}

    i’m toying with the idea of posting a blog entry in the hope of getting some email advice;

    ‘to use semantic id’s sitewide (and have to name stuff all over the place), or use reusable classes’ – what’s your take?

    cheers emil. big aid.

  62. Pingback: 12 Articles and Tools for CSS structuring and optimising | Onyx Design Weblog
  63. I am just starting to document & structure my html and here is the documention i have done so far. Just thought I’d share.

    Documentation of CSS file.doc

  64. @craig: Cool documentation, I have a lot to learn from that one! Thanks a lot for sharing it, I’m sure lots of people will find it useful.

  65. Pingback: Large CSS file management | MadeByPi® Blog
  66. Can’t agree on the Always use the “full path” to elements rule. If you do that you will probably encounter a case later on, which will require you to override the previous rule with a new, more specific one and you won’t be able to do that unless you use the !important CSS rule.

    I’d rather opt for as short selectors as possible and comment my code sections appropriately to quickly find which selector represents what.

  67. This article is great and I utilized most of these techniques for a while until I started to adapt things a bit and I didnt see this technique mentioned in other comments so I thought I’d add my 1cent…

    I now group related properties on the same line, especially position-left-top; width-height; I then sort everything alphabetically. I find this makes the scanning simpler when navigating styles.

    #example{
    position:value; top:value; left:value;
    width:value; height:value;
    }

    I do think the catagory ordering could be useful, especially for font styling and I’ll have to see how that works out in my next project.

    Also using 2 spaces for tabbing is nice too when I start getting into more complex designs

  68. I like to divide my css into multiple files such as:

    general.css
    layout.css
    header.css
    navigation.css
    content.css
    sidebar.css
    footer.css
    other.css

    Then, I have one main stylesheet called default.css whee I import all the CSS files like this:

    @import url('/css/general.css');

    @import url('/css/layout.css');

    @import url('/css/header.css');

    @import url('/css/navigation.css');

    @import url('/css/content.css');

    @import url('/css/sidebar.css');

    @import url('/css/footer.css');

    @import url('/css/other.css');

    This way the individual stylesheet files related to individual parts of the web application are smaller in size (which means I can faster find what I’m looking for and it’s easier to make changes) and contain only relevant styles.

    I also like to order the selectors in individual stylesheet files in the same order as they appear in the HTML markup.

  69. I use to do like this :

    first, I put all global selector like p, h1, etc.
    second, I put generic classes .strong, .clear
    after that, I put my selectors #header, #footer
    and at the end bug fixes.

Comments are closed.