Maintainable CSS: modular to the max!

(Note: this entry was originally published on the Skyscanner Geeks blog.)

In recent years, the issue of getting developers to write CSS in the first place has been one of the big issues facing web standards evangelists — hence the enormous number of articles you’ll find around the web about CSS basics, and techniques to achieve specific visual results. Designers like Dave Shea and Andy Clarke (and many others) have helped us push the boundaries of what is considered possible with HTML and CSS. And although far from all problems are solved (think: multi-column lists), you can usually google around and come up with a recipe to achieve most of the everyday effects that people have come to expect circa 2008.

But putting together a snippet of CSS to give a block of text a background gradient and rounded corners is not the same as building the styles for a dynamic site designed to evolve over the course of several years, and to be worked on by many people in parallel. As Natalie Downe said in her recent presentation at BarCamp London, this is not a solved problem. In many ways, CSS is like regular expressions: much easier to write than to read.

There are many useful techniques for making CSS more readable. Two of my favourites are indenting selectors to indicate element hierarchy or specificity, and keeping the rules in a consistent (e.g alphabetical) order. For example:

div.monkey {
   border:1px solid #99f;
   margin:2em;
   padding:0.5em;
   position:relative;
   }
   div.monkey div.fez {
      background-color:#eef;
      color:#003;
      position:absolute;
      width:200px;
      }
      div.monkey div.fez label {
         font-size:1.2em;
         left:0;
         }
         div.monkey div.fez label.waistcoat {
            left:100px;
            }
      div.monkey div.fez input {
         padding:0.2em;
         }

However, readability is only the first step towards maintainability. No matter how you comment, indent, or structure your CSS, if you jam all your declarations into a single “main.css” file, you’re still doing it wrong.

In his presentation at Fronteers 2008, Stephen Hay discussed separating a site’s CSS into three different files, one to define layout, one for colour, and one for typography. This is not an uncommon approach. Mike Stenhouse calls it modular CSS, and Jeff Croft talked about it in the ALA article Frameworks for Designers. These approaches recognize that it’s madness to keep all your styles in a single file, but they all want to keep the number of CSS files small.

But in cases where you’re working with larger teams of designers or developers, I think this is wrong, and may actually harm maintainability. When you’re working with larger teams, you should be using more files, not fewer. Once you have taken the small step of moving your styles out of a single file and into three, four, or five thematic files, the next big leap is to take that modularity to the max, and create ten, twenty, or more .css files!

But what about performance!? Haven’t we all learned to minimize HTTP requests?

The key to making this work is a build process. A build process allows you to separate your development code (the files you work with) from the machine code that gets served to a browser. Christian Heilmann has been evangelizing this for ages, and almost exactly the same techniques apply to CSS as well as JavaScript.

Development code is what you read and write, and check in to your source control system. It should be highly modular (split over many files), extensively commented, and should make liberal use of whitespace to indicate structure.Machine code is what gets served up to a browser. It should consist of a small number of merged files, and should be stripped of comments and unnecessary whitespace. Your build process is the mechanism with which you apply these transformations. Finally, your web server should deliver the machine code with gzip compression for extra speediness.

Development code is for humans, machine code is for machines. It’s humans who will be maintaining your code.

So what humans see is a large number of files (potentially organized into multiple folders):

  • reset.css
  • grids.css
  • fonts.css
  • headers.css
  • header_navigation.css
  • footer_navigation.css
  • top_adverts.css
  • forms.css
  • etc.

In the olden days, you would bring all of these files together with a bridging file, with @import rules to reference them all. Don’t do that, because each @import rule causes another HTTP request. Use your build process to stitch the files together into a single file (“merged_styles.css”), and serve that instead. Alternatively, you can use a script to do the merging on the fly: Cal Henderson’s article Serving JavaScript Fast describes how to do this.

How you split up your CSS files is up to you, of course. Here at Skyscanner, we use the basic YUI CSS core (rest, fonts, grids) to apply a common baseline to all pages. The content that goes onto the pages is then separated into major blocks, each of which has a very specific ID or class name:

skyscannercss.jpg

If a content block is designed to appear once on a page, we assign it a unique id. If it will appear multiple times, we give it a unique class. Each content block has its own CSS file:

  • id_identity.css
  • id_personalization.css
  • id_searchcontrols.css
  • class_searchresults_selection.css
  • id_flexibleDatesChartViewContainer.css
  • etc.

We have about 70 CSS files at the moment, each one handling the presentation of a very specific part of the site. Inside each CSS file, all of the rules are scoped to that specific id or class name. For example:

#hd_identity {
   float:left;
   height:40px;
   overflow:hidden;
   width:500px;
   }
   #hd_identity a {
      display:block;
	  height:100%;
	  padding:0;
	  margin:0;
   }
   #hd_identity.home {
      height:55px;
	  margin-bottom:20px;
	  margin-top:60px;
   }

The key benefit of this arrangement is that a developer can edit the CSS for a specific content block and be confident that their changes will not affect any other part of the site, because the rules are so narrowly scoped. This is very important when you want to split up work into streams that many developers can work on in parallel.

Depending on your perspective, however, you might see this as a huge drawback. One of the main benefits of CSS, after all, is supposed to be that you can apply visual changes to your whole site by changing a set of common rules. But when you’re working with a highly heterogeneous site with lots of differently styled content and controls, and you have multiple developers all making changes simultaneously, “common styles” are a minefield. You invariably end up with situations where Alice has ownership of feature A, but is reluctant to make changes to the common styles in case they have a knock-on effect on Bob’s feature B — so she adds a bunch of extra classes and exceptions to ensure that her changes stay isolated.

By using a highly modular CSS structure and a good build process, you are embracing that isolation. Most sites and projects spend most of their lifetime in maintenance mode, and a technique that helps reduce the potential for accidental errors when you’re making changes and bug fixes is a good thing.

Microsoft and Nokia adopt jQuery

(Note: This entry was originally published on the Skyscanner Geeks blog.)

Here’s something I didn’t see coming:  Microsoft and Nokia have announced that they are adopting jQuery as part of their application development platforms

What this means on the Microsoft side of things is that they will provide an intellisense-annotated version of jQuery for Visual Studio 2008 (available as a separate download in a few weeks), and will also distribute it as part of the forthcoming ASP.NET MVC release.  Expect it to be even more tightly integrated with the newly announced Visual Studio 2010. (We’re talking about products with 2010 as part of their version name? Already?)

Further notes on the announcement and integration:

We use YUI as the base library for our JavaScript code at Skyscanner, but jQuery is a sweet and slick package. Making it part of the ASP.NET MVC release is a splendid idea. The ASP.NET page model has always felt fat and bloated to me, and the Atlas extensions are a very clever but awkward hack to tap into this model. The combination of ASP.NET MVC + jQuery might actually allow you to write clean web pages with progressively enhanced Ajax functionality out of the box.

Might .NET actually become a cool platform for writing web apps?

Got to get rid of some of these tabs

I’ve got 65 tabs open in Firefox right now. Five years from now, that will seem like a light sprinkling of web dust. Right now, it’s excessive. Time to dump some links:

JavaScript

CSS

Browsers

(With all the improvements going into JavaScript and browsers, client-side development is a great and interesting place to be right now, and the future is looking even better.)

User Experience

“Mainstream Users”

Software development, sexism therein

Note: this is one of my hot buttons. When it comes to gender equality, software development is struggling to come out of the dark ages. What’s worse, though, is that with a few notable exceptions (see below) it isn’t struggling very hard.

Conferences

Business

Travel

Phew.

1 year on

It was one year ago yesterday—Thursday 2nd August 2007—that we arrived here in Oostzaan.

I had taken the overnight ferry from Newcastle to Ijmuiden with a van full of our stuff. I was due to meet our landlord and the rental agent at 11:00, but the boat was delayed, there were roadworks and detours around the ferry terminal, and I got lost twice on the way. It was about 11:40 by the time I got to the house, apologetic and stressed. We took the tour of the house, noted meter readings, and the landlord explained the workings of the gas fire and the digital TV receiver. They gave me the keys, and left.

Abi and the kids, who had taken the plane from Edinburgh to Amsterdam that morning, showed up a little later, around 12:30. We briefly revelled in the sheer size of the house, and then started unpacking quickly, because I had to be back on the road again later that afternoon to catch the overnight ferry back to the UK. I was returning the van in Edinburgh around mid-day on Friday, and then jumping on a plane back to Amsterdam that evening.

That final round-trip might sound like a rush, but for me it was the exact opposite. The months leading up to the move had been a frenzy of work, packing, worry, and pressure. But when I drove off again on that Thursday afternoon, we had made it. All of the timing had worked out. Even if the ferry was delayed, or if I somehow missed my flight on the Friday, it didn’t matter, because I only had me to deal with—no posessions, no nappy panics, no travel sickness.

There was a cinema on board the ship, but the only films that interested me were ones I had seen before. There was no TV in the cabin. I didn’t have a laptop. I was on a boat in the middle of the North Sea, with nowhere to go, and even if I had wanted to do something, I couldn’t have.

I didn’t fancy a meal in the ship’s restaurant, so I bought myself some sweets and some drinks, and retreated to my cabin. I had a book to read: World War Z by Max Brooks. So I lay there on my bed, munched M&Ms, listened to my iPod, and just read. I grew sleepy half-way through, dozed for a while, woke up and read some more. Finished it, and lay for a while contemplating just how damn good it was.

That is my happiest memory of 2007. 2007 sucked massively.

We knew it would be tough, moving abroad. In 2006, we had reached a local maximum in our lives. On the one hand, a local maximum is great, because life is good. The flip side, however, is that almost every move you make leads away from that maximum, which is scary as hell.

But we have taken that hit now, and we’re climbing the up slope again. At the end of 2007, we sold our house in Edinburgh. In January, we made the decision to buy a house here in Oostzaan, and we started viewing properties. In March we signed a deal, and in the last week of June we set foot in a house of our own again. We even have curtains!

Now, exactly one year on, the annual village events that seemed magical and strange to us then are coming around again: the cycle race, the music festival, the kermis (fair). We’ve made friends. Next week, Alex and Fiona will be starting school again, only this time both of them will be at the same school, and this time they both know enough Dutch to speak to the teachers and their classmates. No more day care, no more specialist language tuition. Somewhere in there, Abi and I celebrated our 15-year wedding anniversary. (Crystal. Not much fanfare.)

It was a bad year. One of the worst. No denying that. And the last few weeks, trying to get settled into the house and a new routine, have been pretty tough.

But on the good days, I can let myself hope that we’re back on our way to awesome.

Humble coder

One of the reasons I often dislike Joel Spolsky’s essays is because he makes me feel inferior for not having a Computer Science degree. He doesn’t inspire me to become a better coder; he makes me feel bad that I’m not a better coder in the first place.

Likewise, Paul Graham’s writings often concentrate on startups and the entrepreneurial spirit. Sometimes they’re good; sometimes they have the exact same effect as Spolsky—to make me feel worthless because I haven’t started my own company, and have no intention of doing so.

Rands, on the other hand, writes about management in an interesting and entertaining way, without making me feeling like a failure because I don’t have a team of people working for me. Likewise, I find Jeff Atwood an inspirational writer: in his dedication to coding as a craft, he understands that one of the keys to being a good developer is a fundamental desire to become a better developer. In his latest article, he takes Paul Graham to task for his “you suck” attitude. Thanks, Jeff—I needed that.

I still use this quote from Lois McMaster Bujold as my personal motto:

“There is this, about being the sparring partner of the best swordsman in Caribastos. I always lost. But if I ever meet the third best swordsman in Caribastos, he’s going to be in very deep trouble.”

I don’t know for certain, but I suspect that this attitude would give Paul Graham fits, but it would make Jeff Atwood smile. There’s the difference.