top | item 2376782

Ask HN: Anyone have a really smart way to organize css?

198 points| katieben | 15 years ago | reply

I'd love to see an example of super organized, tight CSS. Do you organize by location (header, footer, body), by function (typography, position data), or both, with multiple instances of the same selector? Wondering how my css stacks up and where I could improve. Thanks! (:

119 comments

order
[+] simonw|15 years ago|reply
Natalie Downe, my co-founder, has a very neat technique for organising CSS which she calls a CSS System. She described it in this talk:

http://lanyrd.com/2008/barcamp-london-5/sg/

She splits everything in to general styles (basic HTML elements), helper styles (things like forms, notifications, icons), page structure (header, footer, layout columns etc), page components (reusable composable classes for components that occur on different pages in different combinations, such as a news teaser) and over-rides (special cases for individual pages, rarely used).

She hardly ever uses IDs, preferring classes for almost everything - because CSS written against classes can be used more than once on a page.

She uses CSSEdit's groups feature to make the CSS easier to navigate - it's all in one file. http://macrabbit.com/cssedit/

View the stylesheets on http://lanyrd.com/ and follow the link at the top to the unminified version to see annotated examples.

[+] tintin|15 years ago|reply
I checked the lanyrd.com stylesheet. I'm sorry to say but if your stylesheet is this big you are doing it wrong. 100K for a compressed stylesheet! So I'm not so sure her technique is a winner.
[+] dfischer|15 years ago|reply
ID's are useful for unique element styling which will always be a case in a website. There's certain elements that are absolutely unique.

Goes hand-in-hand with javascript to ease selector targeting.

I never scope ID's either, that's the wrong way to do it. An ID is always unique so it is top-level.

[+] halles|15 years ago|reply
I think most of you who answered this reply missed the point where CSS is not HTML… ID's should be used when they suit better. The same with classes. You end up constructing semantical html which a) easier to maintain and b) won't mix the design with the content on code-time.
[+] kentbrew|15 years ago|reply
+1 for never styling by IDs, which are global variables and should be used when all else fails.
[+] zefhous|15 years ago|reply
Ideally, I use Sass with Compass (http://compass-style.org/). This alone is a great start to keeping things organized. One of the things I love about Sass is that it allows partials and variable declarations, which both help immensely with code organization.

Then, my code is usually organized as follows. Each section can be extracted to a partial if it gets long enough or if more separation is desired.

  Framework includes and resets
  Variable declarations — colors, possibly specific widths  
  Universal method declarations
  Standard global tags — headings, p, a, ul, li, etc... 
  Generic form styling, usually in a dedicated partial
  Layout — container, header, content, footer
  Then to specific section styling
Since Sass uses indentation, I indent everything in each section within a top level tag. This really helps visually distinguish each section and gives a much less uniform look to the stylesheet which makes it a lot more scannable. If a section uses methods exclusively I'll declare them just above the top-level section tag.

I'm pretty happy with this approach. It was formed fairly organically but become more defined as I use it for more projects. It also seems to work well for both large and small projects, since partials can be used when the code starts getting long.

[+] nagash|15 years ago|reply
The biggest problem that I have with Sass is that the file/line references in your developer tools point at the compiled CSS files, and so you don't have any real reference to where in your Sass files that style is defined. Any solution for this?
[+] storborg|15 years ago|reply
I have four core files:

    reset.css    - I use eric meyer's
    elements.css - Global defaults for things like body,
                   h1, h2, h3, p, a, input, strong. All
                   or almost all selectors in here are
                   just tag names.
    layout.css   - Just sets up the global layout with
                   containers: e.g. header, footer, left
                   column, right column.
    blocks.css   - Reusable chunks.
In addition to that, I use a separate file for each "page type". For example, 'article.css', 'index.css', stuff like that. Some larger sites merit additional files like splitting off 'forms.css', 'tabular.css', etc.

All files get concatenated and minified before serving, obviously.

[+] AyKarsi|15 years ago|reply
What would you put in chunks.css? Could you maybe provide a brief example?
[+] keyle|15 years ago|reply
That makes a lot of CSS files. Google chrome network optimization would tell you to reduce the amount of includes to speed up your site. That said that is debatable since it would be quickly cached.
[+] peng|15 years ago|reply
At some point, the amount of CSS complexity becomes best handled by a preprocessor.

Stylus is great: http://learnboost.github.com/stylus/

I made a post about it, and personally prefer it to Sass and Less: http://nylira.com/stylus-the-revolutionary-successor-to-css/ The hardcore abbreviation mixins in my post seem to offend some coders. When you work in CSS and HTML hours every day though, every character saved adds up to a huge productivity boost.

My current project has 30 directories with 73 partial Sass files, which compile down to one 320kb file.

As to your question, I organize my partials based on controller and url structure.

[+] erikpukinskis|15 years ago|reply
My current project has 30 directories with 73 partial Sass files, which compile down to one 320kb file.

Isn't that a lot to download? That's like 2 seconds on average to download that file in the U.S., and probably in the 10 seconds or higher range for a lot of folks. I guess if the download is delayed to after some kind of engagement (sign up, etc) it's not a big deal?

Is 320K of CSS really necessary? (legitimately asking)

[+] duopixel|15 years ago|reply
After many years doing CSS my best workflow has come to this:

    reset.css //for resetting browsers
    grid.css //if I'm using a css framework
    global.css //styles that are shared across the site
    section.css //styles that pertain a specific section. The name of the file varies, i.e. "about.css".
You need a good code editor that allows you to open files without tabbing or reaching for the mouse, I use Textmate's Command T to switch fast among my files.

reset.css There's a bunch around, I use the one from htmlboilerplate.com, but there's many good ones available. (Eric Meyer's). You will almost never touch this file.

grid.css I only use this occasionally, when I'm working on sites where the grid is very clear and I take out all the stuff I'm not going to use. I usually go for a three col version of 960.gs and trim it to about 12 lines of css. Never touch this.

global.css Here you put your nav, your footer, you body styles, etc. I think that separating by colors and typography doesn't make sense, because you usually change a widget's appearance.

section.css I count on the body tag having a classname, so I can have body class="about" and then do...

    .about section.photo {...}
This way you never override your styles accidentally.

Miscellaneous I avoid the one declaration per line convention when I have similar styles and I want to be able to read them in a table format, i.e.

    .available {background-color: #0f0;}
    .taken     {background-color: #00f;}
    .deleted   {background-color: #f00;}
I usually start from the most generic to the more specific, but I don't worry too much about code order because in the end I just do a search and reach it in no time.
[+] tomfakes|15 years ago|reply
Slightly related, but mainly a formatting issue, I format my css files as such:

  .foo    { x: y; a: b }
  .bar    { m: n }
  .baz    { background: blah blah url(xyz.png) top left;
            x: y; i: j; }
instead of the more commonly seen:

  .foo {
    x: y;
    a: b;
  }

  .bar {
    m: n
  }

  .baz { 
    background: blah blah url(xyz.png) top left;
    x: y; 
    i: j; 
  }
My format takes up less vertical space in the editor. Sometimes, I can get my entire CSS file into a single page on the screen, reducing the amount of time I spend scrolling and searching. I do split lines when they go off the edge of the space, as seen in the .baz example.
[+] eam|15 years ago|reply
I prefer the latter. It's more readable IMO. If file size is an issue, I just use a CSS compressor. Also, it's not too hard in finding selectors, most IDE's or text editors have a "Find" command to locate a selector. That's my 2 cents.
[+] mryall|15 years ago|reply
If you're working on a project with multiple people, having the CSS properties one-per-line helps a lot with determining who changed what in your version control system.

Most of the command-line diff tools don't highlight changes within a single line, and annotation tools usually work on a per-line basis as well.

[+] carterdea|15 years ago|reply
why don't you let your IDE organize your selectors? As mentioned above, CSS Edit does a great job with this. With it, you get the readability of the latter formatting system and the scanability (not a word, I know) of the former system.
[+] karl11|15 years ago|reply
I'm hoping for some good answers here, because I'd love a better way.

I always put universal elements first (body, img, @font-face, etc.), then I just organize it top to bottom by page location (i.e. header, content, sidebar, footer, etc.). I also tab-indent so that elements within another are indented and "contained" underneath, making it easy for me to move from one section to the next. I also write the CSS horizontally, only making a new line for a new element.

I should also note that I'm a n00b :-), so this could be a horrible way to do it.

[+] j79|15 years ago|reply
With the exception of the horizontal CSS (personal preference - unless its compressed, I prefer things on new lines), I like everything you said.

(I actually find the tab-indented elements really interesting and may have to try it on my next project!)

One thing you didn't mention were comments. I've seen some css files with great commenting. For instance, comments at the top that act as an index/table of content for the css file. Very nice!

[+] Skalman|15 years ago|reply
I do it more or less the same way, except I try to separate the layout from its content (I'll put #header, #content, #sidebar, #footer together, and later on define stuff that is specific to the content of e.g. #header).

Also, when having quite a few properties for a selector, it's quite difficult to read when all is on one long line, so I use new lines for each property.

[+] bitsm|15 years ago|reply
I can't recommend Compass/Sass highly enough. A CSS pre-processor will completely free you to organize your CSS however you want, and more importantly, it lets you build up a library of common components (forms, buttons, etc.) that you can easily reuse and adapt for new projects.

Generally, these library files will simply contain mixins (reusable chunks of code), so they don't output anything directly into your CSS, but allow you to include the mixins in certain styles. Very useful for adding effects, rounded corners, etc. on different elements.

Keep in mind however, that mixins can be overused, adding bloat to your code. CSS does cascade, after all. You should always look to see if you can separate reusable css rules to include in markup (commonly seen with grid systems). How you balance out the convenience of keeping your css flexible vs. not littering your markup with lots of styles really depends on the project, but it's something to think about.

I have developed one very useful trick while using Sass for managing colors. Instead of assigning colors directly to an element (very hard to track down later if a change is necessary), I create color variables named after the element and attribute in question. Then in my colors.scss file, I build up my color palette, and after, list all the color variables I created in my stylesheets, setting their values to the appropriate color from the palette (with tweaks, if necessary).

  // in colors.scss ---

  // color palette 
  $red: #ff0000;
  
  // assign colors to elements
  $body-background-color: $red;

  // in layout.css, for example ---

  body {
    background-color: $body-background-color;
  }
Since Sass lends itself to lots of files, keeping all my colors and the elements they are assigned to together in one file makes them much easier to manage down the road.
[+] jarin|15 years ago|reply
I do this, but with a slight tweak: instead of naming the colors things like $red, I try to give them semantic names like $shadow, $highlight, etc. in case I end up having to pick a completely different color scheme.
[+] utunga|15 years ago|reply
Suprised no-one has mentioned Nicole Sullivan's (amongst others) Object Oriented CSS (OOCSS) project: https://github.com/stubbornella/oocss/wiki

She used this approach at Facebook (and Yahoo, I think?) to successfully tidy up a huge code base of thousands of CSS files down to a more manageable few.

I attended her workshop at Webstock and since then had a chance to put it into practice on a 'get it up quick' green fields project (http://chchneeds.org.nz). I must say I was really pleasantly surprised at the way this approach just avoids a lot of the pain points, as a web developer/coder (ie not an html/css guru) I so often face when just getting the simplest things to 'work'.

I guess the hardest thing for me to get my head around to was that to make things more modular you had to let go (a tiny bit) of being so religious about 'semantic html' as a requirement for the HTML, but I think its worth it to get your CSS a whole lot more modular and 'pluggable' together.

Still a bit more work to do, IMHO, but I'm definitely going to be monitoring this project closely.

Nicole Sullivan's site: http://www.stubbornella.org/content/

[+] ChrisFulstow|15 years ago|reply
I'm really interested in the OOCSS approach, it's efficient, maintainable and modular, and although it's not perfectly semantic the trade-off is minimal. I first discovered it from the Velocity 2009 conference, and Nicole Sullivan's talk from Web Directions North - http://goo.gl/yLkby
[+] techiferous|15 years ago|reply
I once tried breaking my css into files according to function (typography.css, color.css, layout.css). It ended up being a royal pain because when I added a new HTML element and I went to style it, I ended up having to duplicate the css selector for that element in three files. I also was constantly switching among the three files to work with one element's styles. So whatever you do, don't organize by function. :)
[+] mixu|15 years ago|reply
my rules:

1) Layout and widgets only.

I start with a reset, then layout (block positioning), then widgets. Everything other than layout is a widget. There are no global styles. If there is one of it, it's an ID. If more, it's a class.

2) No (global) element styles! Ever!

No, not even a p { margin: xyz } or a ul { list-style-type }. Every element that cannot be referred to by class / id must look exactly like it would after the reset.

This avoids complex dependency chains where coincidence influences look. Widgets can be moved from one site to another and you actually have to think new widgets through rather than relying on the default values.

3) Avoid classes and id's as much as you can.

Have single base element with a simple but descriptive class name, and then specify the sub-elements.

For example: Instead of “div.content-title” use “#content h1″ (e.g. div#content with a h1 tag inside it).

Basically, design widgets which consist of one base element, and refer to sub-elements via longer expressions. Use indentation to separate sub-elements.

My strong preference is to maximize for human readability (=short dependency chains, descriptive widgets rather than single elements) rather than short CSS. Cascading within widget-scope is fine, but cascading with global styles should be avoided. I find that when I follow these rules, I like my CSS a lot more.

[+] dfischer|15 years ago|reply
I leverage SASS and Compass for Ruby heavily.

I utilize mixins heavily so I can modulize all my styling and make sure it's included in areas that are appropriate. I've learned this is the only way to handle CSS without styles getting too complicated and accidentally changing something where you didn't mean to.

Example (create a mixin that has certain styles for forms and then include it in a body.wizard page) this way I keep my CSS very dry.

General coding guidelines are horizontal. I recently switched to this. I used to do vertical and indentation but it's very hard to read with big files. I've found that it's a lot easier to read horizontal CSS.

I alpha all my styles from a-z.

[+] carbon8|15 years ago|reply
I also use Sass and Compass. I generally organize the directory roughly like this for projects without a separate designer:

    stylesheets
      - ie.sass
      - master.sass
      patials
        - _base.sass
        - _forms.sass
      utilities
        - _custom_mixins.sass
      vendor
        - _facebox.scss
        
The files with leading underscores are partials which are included in the master.sass. Note that facebox is an scss file. I just dump the CSS in it and include the partial in master.

The nice thing about sass is that it you can change output format, so you can just include all the external CSS files as partials and automatically output a single compressed files with your entire CSS.

When I work with a designer who uses CSS I use a structure like this:

    stylesheets
      - master.sass
      partials
        - _style.scss
      vendor
        - _facebox.sass
In this case, the designer's CSS is dumped in the _style.scss partial, then included in master.sass. Then in master.sass I include my modifications to the designer stylesheets. That way I can leave the designer-provided CSS largely untouched and still have all the flexibility and power of Sass.
[+] PelCasandra|15 years ago|reply
Use SASS with partials and mixins and sort them as it's more convenient for you (probably following the natural flow of descending order of your page).
[+] bdclimber14|15 years ago|reply
SASS has helped me with organization tremendously. With SASS I keep a "typography" partial that is the basic text elements (h1, p, etc.) and font-family variables.

I also have a "colors" partial where I put variables for all my color definitions, such as $light-blue, $dark-gray, and $background-color.

[+] TorbjornLunde|15 years ago|reply
Don't overcomplicate things:

- Have only one CSS-file, unless your project is huge.

- Never use IDs

- Avoid reset CSS (espescially if you can ignore IE6/7

- If you think you need variables (like in SASS), you are probably thinking about it the wrong way

- Give classes functional names, not presentational

- Linebreaks after declaration. (Makes your CSS-file easier to navigate)

- Remember that you can use you media queries inside your CSS-file

Web designer Jens Meiert has some good articles:

http://meiert.com/en/blog/20090401/why-css-needs-no-variable...

http://meiert.com/en/blog/20080515/css-organization-and-effi...

http://meiert.com/en/blog/20070321/css-practice-pseudo-names...

http://meiert.com/en/blog/20090527/css-maintenance-issue-1/

[+] skrebbel|15 years ago|reply
> - If you think you need variables (like in SASS), you are probably thinking about it the wrong way

I've yet to see CSS code for page layout without the usual awkwardness where margin-left of some element MUST equal some other element's width minus some bar's left offset, yadayada. It's for stuff like this that variables make sense. I wholeheartedly agree that if you need a variable to colour two bars and a heading orange, you're probably doing it wrong.

The blog you refer to only has an example with colours, which is just too easy.

[+] evanrmurphy|15 years ago|reply
Use tables for layout instead of CSS. Then your CSS will be more concise (essentially reduced to a theme) and less confusing (because CSS layout properties like float and position tend to cause the most confusion).

Edit: Rephrased to try and better express the idea.

[+] mikecomstock|15 years ago|reply
Here's what I do:

- Almost all CSS goes in 1 big file. One line per selector to keep thinks clean and easy to find. Styles from external sources (like jQuery UI) go in separate files.

- Reset lines go at the top, if you use them, in a / RESET / section.

- Styles for individual HTML tags are next in the / HTML TAGS / section.

- Then a / UTILITY CLASSES / section for clearing floats, etc.

- Next comes site layout. Headers, footers, page width, etc. all go here. Just the layout though - think the grid. No real content styling yet.

- Now sections for each piece in the layout. Content styles go here. First a section for the / HEADER CONTENT /, then a big section for the / PAGE CONTENT / (vast majority of styles go here), then the / FOOTER CONTENT / styles.

[+] ricardobeat|15 years ago|reply
Use less (http://lesscss.org/) - the JS version. Makes your code beautiful: no repetition, hierarchies, concise. Where I work we've used it for about 9 months now and there is no looking back.
[+] bmelton|15 years ago|reply
I haven't used it, as there just hasn't been a project with enough lead time to experiment with something lately, but I'm fond of the idea of code generators for CSS, like CleverCSS for Python and Sass for Ruby.

Other than that, the best advice I can offer that I DO follow is that I group all HTML elements together, all IDs together, and then all classes together. Within each of those groupings, everything is in alphabetical order.

  body { foo: bar; }
  form { foo: bar; }
  h1, h2, h3 { foo: bar; }
  input { foo: bar; }
  p { foo: bar; }

  #container {}
  #footer {}
  #nav {}

  .etc {}
  .even {}
  .odd {}
and so forth.
[+] xdrone|15 years ago|reply
my css is pretty simplistic like this also.

one thing to do is to place class names based on the url with your id's. the class name can be generated from the request_uri (assuming the html code is in a view/template/include).

example: <div id="container" class="contact_us">

then if you need tweaks to a specific page, just add #container.contact_us { foo: bar... }

[+] csbartus|15 years ago|reply
Sorry guys,

After reading all comments it seems there is no (universal) solution to write good HTML/CSS code. Not like in Ruby or Python or other programming languages.

Since this year I'm struggling to create a post / best practices how to code front-end but the problem is too complex (for me).

The biggest issue is how to mark up HTML to have a DRY (minimal) CSS. And how to remember easily these mark up rules to be able to maintain anytime in the future your CSS/HTML.

If you would elaborate your naming / marking up best practices instead of suggesting frameworks/tools maybe that would help better.

[+] kaylarose|15 years ago|reply
1. Separate presentation from layout. For example, all common layout (margin, padding, display, positioning, floats) go in structure.css and color, border styles, background, etc. go in presentation.css. It is far more likely that you will be making presentation changes going forward rather than to your core layout.

2. Only use the minimal selectors you need: div#features ul.feature_list li.feature a{color:red;} could be DRYed up to be .feature_list .feature a{color:red;} which will be far easier to override later.

3. Avoid !important at all costs (sometimes you can't, but try).

4. This is personal taste, but I also usually avoid IDs for styling.

5. Grid frameworks (Blueprint, etc.) are usually overkill, but syntax frameworks (LESS CSS, Compass) are fantastic.

It really boils down to experience, and knowing what you DON'T need - most people add in a ton of extra cruft and end up with hard to extend and debug spaghetti.