Modular CSS

by Alan Ayoub on July 14th, 2009

Modular CSS

Modular CSS is a design pattern for enterprise client side development. As your website grows you might find your backend architecture change, but one thing that tends to stay constant is the client side architecture. Modular CSS is a pattern that emerged as i struggled with exponential website growth.

The goal of Modular CSS is to build a more scalable client side codebase that is easier to maintain and quicker to develop for. Modular CSS prevents CSS from affecting areas of the site that it wasnt designed for regardless of where it is loaded, furthermore, you can easily identify and delete old code with confidence.

Ok, so lets take a step back

Here’s the scenario. You have a distributed team, with lots of people making changes to the client side. They all have jobs to do that dont necessarily sync up with yours. Furthermore, they are not all client side developers. The site is made up of a few hundred page templates, but the complications really start when you add things like multi language support, multi-variant testing, support for multiple brands etc. Bugs are much more difficult to track down when they might only show up in IE6 on the search pages of the Chinese website with test variant 22.5 and brand x. Throw in CSS variable support and post processing tools like sitespect and I’m sure you will agree that things start to get a little bit messy.

Still, some of you may be thinking to yourself that these things shouldn’t matter, “I’m not going to introduce any bugs when i’m writing CSS”! That may be true, but a little short sighted. You may not have introduced any bugs in writing that piece of functionality, however a little bit down the line and one of your colegues may be asked to implement this functionality elsewhere on the site. All to often i have seen big lumps of CSS moved to more common areas to support functionality that it wasnt originally designed for. Think of it this way, You wear your seatbelt while driving not because you think you are going to crash, but incase someone crashes into you. In the same way, you might be the best client side developer in the world, but once you’ve finished with your code, anything can happen to it.

Setting up

In order to have a stable client side you have to make sure your base css is solid. Whether you use a reset style sheet or not, all your common styles should be loaded across all pages.

NOTE:
In this article i use lots of css files. You can of course put everything in the one file if you want. I prefer to use a dynamic CSS solution where CSS is separated into small CSS files or “fragments”. All these fragments are managed in a configuration file and concatenated before being served to the user agent. Dynamic CSS is very powerful, and a topic for another day.

Here is an example of some css fragments you could have in your common file:

  • aa.common.reset.css
  • aa.common.default.css
  • aa.common.layout.grid.css
  • aa.common.layout.page.css
  • aa.common.layout.popup.css
  • aa.common.headings.css
  • aa.common.links.css
  • aa.common.sprites.generic.css

Some of these files should be monitored for changes, things like page layouts, grids, default and reset sheets.

Without further ado

Here are the 3 step basics to Modular CSS:

  • Identify everything you are going to build and give logical parts unique names
  • Use these unique names as top level class names for the individual parts you are going to create
  • Name space all selectors with the unique class names

The examples below shows how a page could be broken into logical parts. The first screen shot shows a page design for a hotel website.

modular_css_example_page1

The second screenshot shows how we could logically spit up the page.

modular_css_example_page_sections1

Tech Design

For complicated projects I like to create a technical design document before writing any code. The document would show the high level markup, css fragments and selectors you plan to use.

Things are broken up between two types of module, common ones and page specific ones. I have named this page “hotel_details” so any modules that are only ever going to be used on this page will use top level classes starting with “hotel_details”.

Doing the technical design first will make you think about what you are going to build in its entirety before you start. It’s also a good idea to share the document with others to get their comments. A Wiki is a good place.

The build

Lets go ahead and build part of the example. We are going to build the 3 widgets at the top. I have picked them as there can be multiple versions of the same module. The example has a map, a photos and a reviews widget. There is also the possibility of additional widgets that are not yet defined.

modular_css_widgets

Required CSS fragments for the widgets

When doing the technical design, i decided that i would build these widgets as common items as i know they will be used on multiple pages. Since we need to create a map, a photos and reviews widget, we are defiantly going to need the following 4 new files:

  • aa.common.widget.css
  • aa.common.widget.map.css
  • aa.common.widget.photo.css
  • aa.common.widget.reviews.css

The first file will be used to create the actual widget container and all common items like the title bar. The last three are used to create the contents of the map, photo and reviews version of the widgets.

Other possible CSS fragments needed

As the widgets will be used on multiple pages, we *may* need some other fragments.

  • aa.[some page].widget.css
  • aa.[some page].widget.map.css
  • aa.[some page].widget.reviews.css

HTML and CSS for the widget container

modular_css_widget_html

aa.common.widget.css

modular_css_widget_css

Note that every selector in aa.common.widget.css is namespaced with the unique top level class name “C_widget”. I use the C_ to denote a common item (its just shorter than using common_widget). Below is what we have just created, a template for widgets. If we didn’t require multiple version of the module we are creating we could have finished off the HTML and CSS with the files we have, and this module would be complete. modular_css_widget_template But we do require multiple versions, so lets continue…

Creating the map widget

Using the template we created above we simply add a new unique top level class for the map version and update the content area of the HTML. modular_css_widget_map aa.common.widget.map.css modular_css_widget_map_css Now we have created the map version. modular_css_widget_map_vd Simply repeat the last few steps to create the photos and reviews widgets and we are done.

Going further

Lets not stop there, there is a scenario where you may need to manipulate the module slightly to get it to fit within a different design. For example, lets say that on a particular page you want the widget map to display in a div over some other content. In this case where would you put the CSS? If we wanted this to happen on our search results page, we could create a new css file called aa.search.widget.map.css and put the extra css in there. aa.search.widget.map.css modular_css_search_widget_map Then add the new class to the top of the module

modular_css_search_widget_map_html

Conclusion

ok, so now we have created a widget template and 3 different widgets. All the HTML and CSS is separated and namespaced. We can easily identify every piece of code making it easy for us to maintain our codebase and prevent bloat. Most importantly we can also reuse these HTML modules anywhere on our site without the CSS affecting any other HTML anywhere. This also means that we can easily change our CSS delivery strategy allowing us to test different configurations in order to optimize performance.

If you’re working on a large site and you don’t have some sort of strategy, your codebase can very quickly get to an unmanageable state. You can end up with spaghetti CSS where it becomes very difficult to remove the legacy stuff without creating bugs.

Have a look at this simplified example below, the left side is what we set out to achieve. Compare that to the right side where CSS is written in a bunch of files that affect another bunch of HTML files.

modular_css_files

Now lets say you want to delete some piece of functionality. Which configuration do you think would be easier to do that with?

Final thoughts

This took slightly longer to explain than I thought it would, possibly because I build websites for a living and don’t write articles. Anyhow, in order to keep it this brief (yes, this is cut down a bit) I had to omit some detail. Nothing serious but to get the full picture i will need to write a bunch more supporting articles. If people find this one interesting i might just do that.

DeliciousFacebookDiggRSS FeedStumbleUpon

From CSS

3 Comments
  1. Dom permalink

    Your approach makes a lot of sense to me. I fairly new at web design and after a few hurdles I finally decided to do some research. Your approach goes far beyond but is hand-in-hand with the clarity of Mike Stenhouse’s Modular CSS page @ contentwithstyle.com.

    I would love to see more articles from you!

    Thanks a bunch,

    Dom

  2. Hi

    Nice idea. It helps make the hierarchy or cascade very clear. I see a problem tho’.

    My client and I recently ran into a frustrating IE quirk (v8 and lower). Ok, this happens on a daily basis, but this one’s relevant to your article. IE enforces a limit on the number of CSS files included in a page. It also imposes a limit on the number of distinct CSS rules, but we hit the file-limit first.

    Your method could easily result in pages requiring a LOT of files. Do you have a way to cope with this?

  3. Alan Ayoub permalink

    Hi Simon, yes I know of this restriction. IE only lets you have 32 of the same linked resources. The thing is, you really should be concatenating the files before delivering them. Each http request costs about 0.1 seconds or more in latency. This particularly affects older browsers that only support 2 concurrent connections.

    That said, I suggest two set-ups, concatenate and minify the files for production but not in your development environment as it make it harder to debug.

    To circumvent the issue in your dev environment you can use nested @imports, these are also limited but I hope you will never reach that limit (32 resources at a depth of 3). If you don’t feel like writing custom functionality to deliver your CSS files in different ways for production and development I guess you could use @import for both, however it isn’t recommenced as stated in the YUI performance guidelines.

    Regarding the rule limit, I really think if you ever hit that limit there is something wrong and you need to go back and reassess what rules you are delivering for that particular page. The nice thing about this setup is that you can easily do that without causing and conflicts or other problems.

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS