Latest: Genstatic, my first sip of coffee

Content with Style

Web Technique

Modular CSS

by Mike Stenhouse on May 18 2005, 08:47

This isn't a new idea but looking at people's code it doesn't seem to be a particularly widely used practice: modular CSS. That's a poncy name for the very simple idea of grouping related styles into separate stylesheets. The same set of tasks turn up on project after project and a little careful thought can save hours of foundation work, allowing you to get on with the serious business of turning a flat design into a web page far more quickly.

The broad groups that I use are: typography, forms, layout, navigation and colour. These aren't set in stone and some projects require more or less categories.

Common components

Typography:

Basic styles for html elements with font faces, sizes, weights and neutral colours. Bearing in mind that colour is dealt with elsewhere you'll probably only find you need to make minor adjustments to these between projects – a couple of ems here and there, bold to normal for a heading or two, that sort of thing. I limit the styles in this sheet to root elements only – no classes or ids. Anything requiring a class is probably going to be site-sepcific and so belongs in layout.

Forms:

Forms are my least favourite things to try and style - the variation between browsers often forces lots of ugly hacks and filters and I like to keep these separate from the rest of the CSS.

Navigation:

How often have you coded a horizontal nav bar? Do it once, do it well, and reuse it. You'll need to tweak a few bits and pieces but put it in it's own CSS file and the bulk of the work will be a copy and paste away.

Layout:

This is where the majority of the work lies and most of it will be unique to the project you're working on. I use naming conventions for my common structural elements to ease the transition between sites when it come to maintenance but that's off-topic for this article.

Colour scheme:

The only properties you'll need in here are: color, background and border-color. Nothing else. Be sure to avoid adding any layout info here – a misplaced margin:0 can ruin your whole afternoon!

An added benefit of the separate colour stylesheet is that you can write yourself a nice neutral colour scheme and avoiding 10 hours per day of staring at the eye-searing orange that your client is insisting on.

On a similar note: Stop Design | Introducing Bleached.

Possibly of interest here: And All the Malarkey | Black and white: Day five.

Putting them all together

I use a file called screen.css but it can be whatever you like. All you're doing here is @importing your CSS modules to make up a complete site. The @imports cover N4 degredation so you can just <link> to screen.css from your HTML.

/* typography styles */
@import url("typo.css");

/* form elements */
@import url("forms.css");

/* main layout */
@import url("layout.css");

/* navigation */
@import url("horizontal-nav.css");

/* colour scheme */
@import url("skin.css");

For your print stylesheet you might choose to just import your typography. Rather than having a print sheet that overrides all your layout just have it import typo.css and nothing else. Job done. What about handheld media types? Well you might want a flexible layout but the same typography, form styling and colour scheme. Modular CSS comes to the rescue and you only need to code a new layout and import it into handheld.css along with typo.css, form.css and skin.css.

This technique also allows you to unplug stylesheets globally from your site without having to touch the HTML, adding a layer of abstraction between content and style.

Another happy side benefit of modular CSS is in the debugging – just comment out whole stylesheets until you isolate the problem and focus your efforts there.

Addons:

You could plug in a development stylesheet with Andrew Krespanis' Global Whitespace Reset (Left Justified | Global White Space Reset). Before you hand over just remove the import from screen.css and you're good to go.

If you find that your're reusing chunks of code from previous projects for promo boxes of headers, consider placing them in their own stylesheet for easier access later.

A word of caution

The more stylesheets you have the more you, the developer, have to remember and keep track of. Where did you set the padding on that element? It could be in a number of places and if you're not used to your system, or you're not consistent with it, things can get frustrating. Set yourself some guidelines and stick to them to give yourself a fighting chance of taking an educated guess at where you might have placed your rules. Consider putting these guidelines in comments at the top of your files – these can help to keep you on topic while you're coding as well as setting you off running when you come to make maintenance changes months down the line. Something as simple as sensible naming conventions for your CSS files can be a great help.

Comments

  • Curious: why would you use the Global Whitespace Reset as a development stylesheet? Why not incorporate it into your typography stylesheet and leave it there?

    by Tony on May 18 2005, 23:10 - #

  • I find that clients have a habit of using tags I never thought they’d ever need, and leaving the global whitespace reset in guaruntees that if they do, thay’ll be on the phone. With whitespace left to the browser default on tags that I’ve not thought of I at least stand a fighting chance of things looking okay until I can fix things properly. I’m not sure I’ve explained that too well but do you see what I mean?

    by Mike Stenhouse on May 18 2005, 23:36 - #

  • nice page

    how to create a 90 degres text for any browser

    by nesz on May 19 2005, 23:13 - #

  • That looks like a good technique. I’ve recently watched the CSS on a website my wife and I are building together balloon out of control, and this looks like a technique that might help make things manageable again. (It’s the first time she’s tried to use CSS, so I hear the frequent cries if “aaaaaaaaaaaaagh! I hate CSS!”...)

    by David Lynch on May 19 2005, 23:33 - #

  • I know that feeling! It’s especially powerful when you have tried and tested sheets on several sites… Then you can be confident that the basics are right and you can get on with the serious business of making everything look ‘proper’.

    by Mike Stenhouse on May 20 2005, 02:47 - #

  • Excellent solution.
    Not only can it simplify the process, it also expedites changes as I now don’t have to search or scroll through lines upons lines of code. I will definitely be looking into modulizing (sp?) our CSS.

    by M Kristof on May 20 2005, 04:40 - #

  • One thing to keep in mind with this technique is that you’re turning one HTTP connection into five. It may be worth it to have manageable code, but load times are always something to consider.

    by Joshua Bereiter on May 20 2005, 05:37 - #

  • You got a duff link there Mike :( My file extensions are .html

    (Nice article! Via Andy Budd)

    by Malarkey on May 20 2005, 09:03 - #

  • @ Joshua:

    Having the CSS split into single modules makes sense if U consider that most “average” users turn on browser caching (or leave it turned on).

    So once loaded you can have the reusable parts cached and just pull in the changed parts. I like Mikes idea as well, but most times my approach is to split stuff into navigation, header, footer and typography, then exchange the content bit by using wrapper css files with @import.

    Any other thoughts on this?

    by Pascal Opitz on May 20 2005, 09:56 - #

  • Ooops, sorry Malarkey. I’ll fire my editor. It’s cured now…

    by Mike Stenhouse on May 20 2005, 12:46 - #

  • Pascal:

    True enough, once the CSS is cached it makes no difference. The issue I see is the initial load time. I don’t think the importance of having the first load happen as quickly as possible can be understated.

    Another issue I see is the duplication of selectors. Having multiple instances of your selectors for every type of rule could add considerably to your overall CSS filesize.

    Both of these issues may be trivial when one considers HTTP pipelining, gzip compression, and all the other means we have to optimize HTTP connections, but if I can shave half a second off my initial load at the cost of less manageable CSS, I will. In the end it’s one of the thousands of tradeoffs that has to be made when designing a site.

    by Joshua Bereiter on May 20 2005, 18:31 - #

  • Just make your master css a php file that pulls in the files like includes.

    spidering off 5 connections is a waste of resources.

    by Non on May 21 2005, 01:36 - #

  • Yeah Non, that’s a good idea if you want to save on requests.

    The point of the article is more the breaking down of your stylsheets into their functional parts than the recombination.

    The problem with putting everything back together on the server side is that you then can’t take advantage of client-side caching if you drop in other sheets on specific pages. I normally separate the home page layout from the rest of the layout, for example, because there’s no point serving it to every page. I also tend to swap layout sheets to switch between 2 column and 1 column page variations etc rather than switching on body id or the like. See my CSS Framework article…

    At the end of the day, what you do will depend on the requirements of the project and your personal preferences.

    by Mike Stenhouse on May 21 2005, 13:26 - #

  • I use PHP instead, as part of an overall modular design. If you’re curious, have a look at this section of my article on building modular XHTML pages with PHP:

    http://loadaveragezero.com/vnav/labs/PHP/head.php#code

    Around paragraph seven of that section I explain how I conditionally import the extra stylesheets. You may enjoy also following the link via my signature to this comment as I just added this article to my developer’s resource DB. ~d

    by Douglas Clifton on May 23 2005, 02:42 - #

  • @ Douglas:
    Doesn’t that get to the same point of loosing the client caching again?

    by Pascal Opitz on May 23 2005, 09:19 - #

  • Pascal:

    Why would adding link @import elements to the head of your document for each CSS module prevent the browser from caching the stylesheets? The stylesheets themselves aren’t dynamic.

    by Douglas Clifton on May 23 2005, 10:39 - #

  • @douglas:
    point! that happens when you post comments before you think about it ;)

    by Pascal Opitz on May 23 2005, 10:57 - #

  • Actually, to clarify: one style element with one or more @imports.

    On a side note, I recently wrote an article for Digital Web about dynamically generated CSS using PHP. That was the number one reaction by far: but dynamic CSS is slow, the browser doesn’t cache the results! First of all, unless your host is heavily loaded, generating something simple like CSS with a scripting language like PHP is almost as fast as a static file. And the “almost” bit is so trivial that no one would ever notice it unless you happen to run with snails. I’m even aware of situations when dynamic content is actually faster than a disk file. As far as the caching issue goes, that is trivial to fix.

    Yet one post after another, dynamic CSS is slow! The browser doesn’t cache it! Sigh. ~d

    by Douglas Clifton on May 23 2005, 18:26 - #

  • My big css problem is:

    to let topstyle format code or not?
    (i mean alfabetical ordering…)

    by Baldus on May 23 2005, 22:24 - #

  • Douglas: I think the misunderstanding was going back to Non’s post. He suggested using PHP to replace @import – making one long stylesheet to save on server requests. I’ve got no problem with generating stylesheets server-side, since these newfangled computer-thingies are alarmingly quick, but I’d favour a method that resulted in several sheets so that the common ones could be cached.

    The key benefit of this technique for me is the reusability though. I use my typo.css and forms.css sheets again and again between projects with only minimal changes. I’ve also got a tools sheet that contains classes for markupless clearing of floats, accessible hiding and image replacement, which I use over and over.

    by Mike Stenhouse on May 24 2005, 00:58 - #

  • I wrote a follow-up article regarding modular CSS and efficient reuse for some additional thoughts. I wonder what you guys think. Comments are welcome!

    by Klaus Hartl on May 24 2005, 14:18 - #

  • Mike:

    Right, the comments regarding using PHP to generate CSS were an aside. On my site (for the most part) I only use PHP to generate the style element that @imports the various extra stylesheets: forms, tables, code, etc…very much in keeping with your article.

    I only brought up the topic of caching because as soon as many people hear “PHP” and “CSS” in the same sentence they all start in on how dynamic CSS is so slow. If done correctly, this is simply not the case. I guess preventing more misinformation was my goal with that post.

    New favicon? heehee, Doug

    by Douglas Clifton on May 24 2005, 16:48 - #

  • Doug: Ah, my bad – sorry. I really like the idea of using PHP to just include the stylesheets you’re going to use on that page. Table styling, especially, gets very weighty very quickly. How do you flag which pages use which sheets? Some clever RegExp/XSL detection? The demo pages use PHP to include the relevent layout stylesheet, although in a very rudimentary way.

    The favicon is nothing to do with me but I like it! It feels like Pascal’s doing…

    by Mike Stenhouse on May 24 2005, 16:55 - #

  • Yup, new favicon :)

    by Pascal Opitz on May 24 2005, 17:09 - #

  • Mike:

    I build each page with a series of modular PHP functions that mirror the structure of an XHTML document. One of which of course creates the head element. All pages use the root.css stylesheet. If I need to pull in more, I simply pass an array of them to the head function: head(array(‘forms’,’tables’));—same thing with extra Javascript libraries (although I don’t use them very much, being a server-side kinda guy).

    Pascal:

    Why you little sneak! Actually, if I’m right and you got the icon from the one I created yesterday then you guys are the first to do this (that I’m aware of) and it makes me smile to know this. Personally, I use the favicons as a mnemonic tool for my listings in the DB. I can visualize what page I’m about to visit just before I click through to it. Minor eye candy too. Not sure if my visitors benefit from it or not. If a site I list doesn’t have one, then I create it. If the owner likes it and uses it, well, that’s great!

    by Douglas Clifton on May 24 2005, 17:53 - #

  • Nahh, I just think it was missing …
    I have one on my portfolio-domain www.pascalopitz.de since ages, but as we just started up there’s much room for improvement here …

    by Pascal Opitz on May 24 2005, 20:51 - #

  • All that work for nothing! It must of taken me at least 2 minutes. heehee

    by Douglas Clifton on May 25 2005, 05:38 - #

  • ...I’ve been checking my referrer logs, and noticed that six or seven people have been following that link to my messy CSS per day since I left that comment. So I felt that mentioning an updated version (on a development server, as the live site hasn’t been updated since I made the changes).

    To really be in line with the article, I’d need to shift some rules from the typography stylesheet to the layout sheet. I just went through my old CSS and did a lot of copy-paste to split things up by type.

    I was slightly surprised to note that there wasn’t much of a size increse in this. All the new files together weigh in at about 0.7kb larger than the old monolithic stylesheet. I was expecting more, considering the selector duplication.

    by David Lynch on May 25 2005, 21:16 - #

  • Of course, I’d look smarter if I remembered that whole Textile linking thing.

    The updated stylesheet

    by David Lynch on May 25 2005, 21:19 - #

  • This seems a useful methodology for bringing order to my usual chaos. I have been heading this way but you have set it out really neatly. I have been evolving an Initialisation section for global resets, hacks and other universal monstrosities. Thanks.

    by Root on May 26 2005, 23:59 - #

  • Very interesting article, but I do not understand one little thing : one time you speak about screen.css, and after about shell.css. What is the difference ?

    Thanks for you answer !

    by Sébastien on May 27 2005, 07:30 - #

  • Sorry Sebastien, that’s typo on my part. They should both read screen.css, which is the container I use to @import my screen media stylesheets. I’ve also updated the paragraph following that because, reading it back now, I’m amazed anyone understood it. Cheers!

    by Mike Stenhouse on May 27 2005, 15:47 - #

  • rouping of styles can be done also like this

    screen.css
    print.css
    alterantestyles.css

    layout.css
    nav.css
    js_enabled.css

    splash.css
    sectionsA.css
    sectionsB.css
    comments.css

    screen.css
    basicstyling.css
    iewin.css
    ie5mac.css

    It all depends on what styles are you reusing, which styles I can load already, which browsers I target (important !!).

    also when it is cut up in different files, it loads chunk by chunk, although not all chunks are equal loads

    by Huckleberry Straw on September 27 2005, 10:30 - #

  • Yeah, absolutely. How you break up your stylesheets completely depends on what makes sense to you and the project you’re working on. I go for slightly larger chunks because that’s how my head works best but if you can keep track of more files then by all means do!

    For example, I like to keep my hacks along with the rules they’re over-riding so that I don’t lose track of them, but I also appreciate the advantages of keeping them in separate stylesheets. (I stopped doing that after spending ages trying to debug a sheet only to find that the rule I was grappling with was being reset elsewhere and I didn’t realise.)

    by Mike Stenhouse on September 28 2005, 04:30 - #

  • Great article Mike, I believe this is the most extensible way to develop and maintain CSS. I hope to apply this in my next little project :)

    by Ash on October 10 2005, 18:48 - #

  • 5 connections? What web server from 1995 are you using that doesn’t support HTTP 1.1 with persistent connections (Apache “KeepAlive”)?

    5 requests perhaps.

    Not the same concept as 5 connections by far.

    by Jeff on October 11 2005, 10:48 - #

  • Great article

    by Martin on October 26 2005, 17:59 - #

  • You could include extra rules (ie. ‘where did i set the padding?’) as comments in the stylesheet

    by Tinus on October 31 2005, 08:51 - #

  • Several issues as conclusion from the comments :
    1. 5 connections is bad for clients
    2. php is a solution that can minimize 5 connections
    3. php wont cache right (why?)

    Now an integration of these comments brings out this idea :

    A php script that will import all 5 stylesheets—while he’s importing, also do some basic processing of the styles to combine similar definitions.

    Example :

    1. these tags are in different files :
    h1 { font-family: sans-serif; font-size: 10em }
    h1 { margin-left: 3em; }
    h1 { color: blue; background-color: cyan; }

    2. the php script combines it all into one tag like so :
    h1 { font-family: sans-serif; font-size: 10em; margin-left: 3em; color: blue; background-color: cyan; }

    3. the php script sets its time correctly . . . to the last updated css file (if you update color.css last, then that is the time php script should send out)

    This way what will happen is :
    1. proper caching will work (right times reported)
    2. multiple (5) connections is not an issue
    3. css taking too much “space”/”bandwidth” is not an issue
    4. extra connections for style wont happen
    5. modular css is still managable!
    6. php script is a real easy one, and might be fast (enough) as well…

    is there anything that I am missing?
    anything anyone wants to suggest extra?

    by Evgeny on November 2 2005, 13:10 - #

  • Hmmmm, that sounds interesting. You’ll have to make sure that the script combines the rules in the order they are imported (as in your example). It would probably be worth adding whitespace stripping to the final files as well for a bit of added compression.

    The only issue for me is that I use combinations of stylesheets across pages within a site. By that I mean that the home page might have:
    @import url(“typo.css”);
    @import url(“layout.css”);
    @import url(“home-layout.css”);
    @import url(“horizontal-nav.css”);
    @import url(“skin.css”);

    While a cotent page might take:
    @import url(“typo.css”);
    @import url(“forms.css”);
    @import url(“layout.css”);
    @import url(“horizontal-nav.css”);
    @import url(“skin.css”);

    The idea is to use browser caching to my advantage – only feeding new sheets as they are required. Your technique wouldn’t work for all the sites I work on but it would definitely be very useful for some…

    Good idea!

    by Mike Stenhouse on November 3 2005, 06:15 - #

  • Great idea ! I love it. I must do that with my next project.

    by nemanja on November 7 2005, 13:57 - #

  • thanks for de resource

    by ea barcelona on November 11 2005, 18:14 - #

  • If you’re going to go to that length, you might as go one step further; parse the CSS, combine it into a single logical file and cache it.

    As an example:
    1) First hit to the site, do I have a valid cached copy?
    2) If no – read, parse, optimise, save final product
    3) If yes – send the cached copy

    Using that sort of a method, you wouldn’t have to read/parse/optimise the files each hit on the site.

    Al.

    by Alistair on November 23 2005, 06:25 - #

  • Hmm, are we now talkin to optimize the CSS on the fly or on change?
    Alistair: If you combine all files for each page into one file you would loose caching of parts, e.g. the navigation.
    Evgeny : optimizing the CSS files on the fly or on export and combining multiple blocks into one could bring up problems with selectors and specifity. However, you might wanna check out CSSTidy to do what you want to.

    by Pascal Opitz on November 23 2005, 10:09 - #

  • Thank you. That’s EXACTLY what I was looking for.

    by T-Sugar on December 24 2005, 07:07 - #

  • I was absolutley amazed by this tutorial! It makes my life SO much easier whistles it’s easy, and not difficult to implement. I know I’ll be using modular css from now on!

    I was actually looking for another coding solution to a problem I had when I found this site. My website is skinned, and I would want a tagboard that uses the css of the specific skin (not the regular importing css code that imports from a specified location). I was looking for a code that just imports the stylesheet of the specific skin. I’ll try looking around this site if you have such a code, but in any case, thanks! :)

    by Sara on January 6 2006, 23:24 - #

  • PS: I’m sorry for being redundant in my last post :P Again, thanks! :)

    by Sara on January 6 2006, 23:36 - #

  • 1st: Thank you for this article and it

    by tarmac bison on January 8 2007, 19:06 - #

  • About dynamic CSS being slow, why not use dynamic CSS during development then static CSS in production ?

    I like Daniel’s approach which uses the best from both worlds:
    PHP-generated CSS magic

    by hugo on January 12 2007, 13:20 - #

  • Very nice explanation and approach. We’re considering some similar server side approaches for various reasons.

    by Frederick Townes on July 12 2007, 00:12 - #


Comments for this article are closed.