2010.06.17

How I structure CSS files

Yesterday I was having dinner with my coworkers (company party!!) and between some bottles of wine, Italian food and Bocce, Marcus Schaefer commented that my CSS are really organized and I briefly explained why I do this way to him and thought that it was a good subject for a blog post…

The purpose of this post is to explain a little bit my workflow and how I setup my CSS files and why I do this way. I’ve been using almost the same structure on the past 3-4 years and it has been working pretty well, it’s the way that I find more productive/organized for my way-of-thinking/workflow and I’ve never seen someone writing about and/or using the same approach.

Keep in mind: each person has their own opinions/preferences and my setup may not fit other people’s workflows…

How it all started…

I still remember the first time I saw a tableless website, I was looking at the source code to try to figure out how to replicate a roll-over effect and at that time I didn’t even knew that CSS could be used for other stuff besides changing the scrollbar and link colors.. I thought that they were using some kind of magic and that I would never learn how to do those things… - It was back on 2004 and I had just started my Graphic Design Bachelor after graduating as a Technician on a Business Management school (together with high school), so I wasn’t coding that much back then… - Almost 1 year later I started reading many tutorials/articles (specially on a Brazilian website called Maujor) and coded my first tableless website, after that CSS became my favorite web technology and remain as so until now…

My default.css file

IMPORTANT: My default.css file evolved over time and it became the basis.css framework. Info about the way I order rules still relevant but I’m not using this default.css file anymore.

All my projects starts with the exact same CSS file called “default.css” that stays on my computer desktop all the time and that is also the preset for new CSS files on my Eclipse preferences.

After reaching a stable version (or after some good progress on the development) I usually also add a date after the @version number like: @version 0.3 (2010/06/17) and update the version number at each update, just to remind when the file was created/modified.

PS: the “Awesome Website” really makes part of my default.css file, just to start the project with some positive thinking :) – I replace it with the project name at the beginning of the development so I don’t forget it.

The order is important!

One of the most important things is to keep the code organized in a logical way, so you can browse it quickly and avoid overwriting rules that you don’t want.

I always separate the rules based on the type (reset, tags, generic classes, structure) and also based on the order-of-appearance on the markup. – e.g. #wrapper should come before #header, ul should come before li, and so on…

I also “group” the rules by “categories” (separated by space) so everything from the footer will be at the same place…

Rules that applies to all pages should come before specific ones.

Why do I follow this specific order?

One of the hardest things to understand and to master in CSS is specificityof course it loses for the box-model, float, overflow and display modes.. but still hard – so if you keep this order is less-likely that you will get confused about what is being overwritten since the most specific also are the last rules on the file.

Reset

Nowadays most people already knows what it is and uses some kind of CSS reset to reduce the browser incompatibilities, the most popular ones are Eric Meyer’s and YUI reset.

Why create a custom reset instead of using YUI or Eric Meyer’s?

Before reading some article a long time ago (maybe 2006-2007) I was using the simplest technique possible to reset the browsers default properties: *{margin:0; padding:0} – but as the article pointed out, this isn’t good for performance and you can end-up changing more than you actually want, so I decided to stop using this technique. At that time I thought that Meyer’s approach was too big and that he was doing way more than I needed, so I decided to code my own stripped-down version (it was simpler than my current one)…

Some time ago I even started to create custom resets based on the tags that I will use on the project; I start with all of them and delete the ones I’m not using (specially for mobile websites), since mobile devices has a very limited performance.

Edit: I went back to Meyer’s reset since it is very stable and well known. Another option is to use normalize.css instead of resetting your styles.

General Tags

All HTML tags that needs some generic/default styling goes here. I don’t use any CSS class or ID here.

Generic Classes

Styles shared among multiple elements and/or classes that are used on more than one section/page/html block for instance .last, .odd, .error, etc..

Structure/Content

Styles that define the page structure and/or are directly related with the page content – e.g. #wrapper, .mainNav, etc..

Hacks

I usually use this part to add browser specific (basically IE) hacks during the development phase, after finishing the development I usually remove the code from this section and add it as a separate file using conditional comments. – I’ve stopped using conditional comments and moved back to CSS hacks, conditional comments usually causes more problems than it solves, I also stopped separating hacks from regular styles to avoid duplicating selectors which could make changes be out-of-sync. Usually a simple website (my portolio, my blog, etc) doesn’t require hacks, but sometimes there is no way to avoid it..

This website has a list of the most common IE 6-7 CSS bugs and how to solve them. Avoid using hacks whenever possible.

Debug

Styles used for debugging purposes, removed before deployment.

Why all the properties are on the same line

A couple years ago I was using almost the same conventions but instead of keeping all the rules of the selector on the same line I was breaking each property into a new line, so why did I stopped doing like this?

Avoid scrolling
I’m sure a lot of people will find it harder to read, other will find it easier, it all depends on your preferences. If you don’t like it just use a CSS formatter. – I think it saves me some good amount of time.
Performance (File Size)
Not really a valid point since you could do the same thing before deploying the site but that way I don’t even bother compressing my CSS files since it is already kinda compressed. – view comment #3 for more details
I’ve got used to it
After the first project there’s no way back…
Changing properties isn’t that common
Finding the property is way easier than to find the proper selector – it’s hard to have more than 10 properties for a single selector
Easier to find the proper selector
You can browse the file quicker since many selectors are on the “same fold”.

Nowadays I’ve been working on larger projects so I’m breaking my CSS into multiple files and keeping each rule in a separate line, only using the single-line approach in small projects (so I keep the amount of lines small). added 2012/03/13

When the project/file is too big

Most of the time my projects have a single CSS file (avoid multiple HTTP requests, cached between pages, etc..) but when the file start to get too big (more than 300 lines) and a specific section/page that the user may not go to (e.g. shopping cart) has a lot of different rules (e.g. 25% of the file size), I usually split that section into a new file to save bandwidth and also because it helps to keep the files organized and makes the CSS easier to read/maintain – when the file is too big you end up scrolling too much and getting lost.

If the file starts to get too big it is a good idea to check if all the rules are really being used, there are a couple tools that can help you like Page Speed and CSS usage.

In case your project is really big instead of just using “comments” to split sections of your file split them into different files (reset.css, general.css, generic.css, structure.css, home.css, contact.css, etc..). Consider using a build tool like Ant, make, rake to concatenate your CSS files for deployment. I’ve been using the RequireJS optimizer to merge @import(ed) stylesheets.

To sum up

I consider organization as being a really important skill for developers since it makes debugging/maintenance/collaboration easier and it’s something that I try to keep on all projects but don’t take it too serious, of course a crazy deadline and/or lots of changes requests can make everything “go down the toilet” and also if you are doing something really simple there’s actually no need… It’s just an advice and I hope it’s useful for someone, at least for me it was a HUGE change/improvement on my workflow.

To cite a friend: “The only thing worse than other people‚Äôs code, is your own code 6 months later.” — Zeh Fernando

Read More

That’s it!

Changelog

2010/07/16:
added some notes about larger projects and why I keep all properties on the same line.
2010/11/11:
updated default.css and added new notes about hacks and debug sections.
Edit 2011/01/09:
updated default.css and moved it to GitHub to make updates easier, updated “hacks” section and added info about build tools and split files to “big projects”.
2011/05/03:
Added note about going back to Meyer’s reset.
2011/07/20:
Info about default.css becoming the basis.css framework.
2012/03/13:
Added “Read More” section and info that on large projects I break each rule into a separate line.

Comments

some extra tips (that I also use) to optimize my CSS files: How to micro-optimize your CSS.

Good stuff, thanks for sharing :)

Do you remove the code comments for production use? They seem heavy given the clean, concise contents of the CSS code.

Also, here is a collection of CSS reset styles commonly used today. Lots of choices!

Usually I only remove the comments and line breaks when performance is a big concern (e.g. website for a mobile device and/or high-traffic website) but I always check the score using YSlow and PageSpeed to make sure it isn't affecting too much.

I avoid to do this kind of optimization because a less experienced developer may need to make updates (and may not be familiar with compression), files may be out-of-sync (changes made directly into the server files), etc.. - If you have an automated build process (like an Ant task) it is more acceptable but you are still vulnerable to changes made directly into the server files.

Nice article!

You mentioned above that you use Eclipse, have you taken a look at Aptana Studio 3 (it is still in beta)?

First, thanks for the blog post, I've just subscribed to your blog via Google's RSS reader and I am looking forward to future posts.

I work with my CSS a bit differently. Instead of having /* == HEADER LINES */ in a single big CSS file, I break it up into multiple CSS files. Some projects end up with 20+ individual CSS files. They are all included in a particular order with reset.css being first and a 'common.css' second where I put commonly used classes.

Before I push the site live, I have a build script that will automatically scan the index-dev.html file, find all my CSS includes, concatenate them in the correct order into one file, minify them and produce a single index.html file that has just one CSS include.

This allows me to have have the niceness of multiple CSS files during development mode, and still have nice performance come production.

Also I noticed someone suggested Aptana Studio. I used Aptana in the past, and I found that once the project gets to a certain size, Aptana slows down to a crawl. I haven't checked it out in over 6+ months though, so maybe the engineers made performance an actual priority recently and maybe the newer versions are faster.

Super Duper: I'm not sure but I think Aptana 3 is more focused towards Ruby and I use it mainly for PHP and JavaScript. (for CSS/HTML I use more Notepad++) - I installed it a couple weeks ago but since I couldn't find a way to install the Ant panel I decided to go back to Aptana 2 (as an Eclipse plugin), I will try it out again later...

Robert: using a build script is a really good idea and I've been using it mainly to compress/combine my JS files, copy files to the deploy folder, run JSLint, generate documentation, etc.. - since usually my CSS files aren't that big (small websites) I still use a single file even on the development phase.

A nice tool to combine multiple files is Nicholas Zackas Combiner, just simple comments inside your CSS/JS/TXT files.. - but I'm still using just the Ant concat task, your approach seems better since it is more automated.

I wish Aptana was as good as FDT.. - I only use it because it's free, I don't know any other good editor that supports PHP/CSS/JS/HTML and I kind got used to Eclipse.

cheers.

I have a question on base characteristics of some elements over ridden in the the first style definition that is "vertical-align: baseline;" and element like "sup" and "sub" having have different behavior itself but forcing elements to change the base characteristics. Is it really required? If some one want to use "sup" or "sub" will have to write another style to have it base characterstics?

@shajith It isn't really required in most cases, a different approach is to use normalize.css instead of resetting all the base styles (Eric Meyer reset makes all the elements look the same). Normalize will be a better approach for projects that follows a regular structure (if H1, H2, P, etc, shares the same styling across multiple pages/places) while resetting will give you more freedom when the styling of the elements is so unique that it doesn't make sense to have defaults.

Leave a Comment

Please post only comments that will add value to the content of this page. Please read the about page to understand the objective of this blog and the way I think about it. Thanks.

Comments are parsed as Markdown and you can use basic HTML tags (a, blockquote, cite, code, del, em, strong) but some code may be striped if not escaped (specially PHP and HTML tags that aren't on the list). Line and paragraph breaks automatic. Code blocks should be indented with 4 spaces.