Using IDs in CSS

I made the decision a while back to not use ID selectors in my CSS code. Although the decision was informed by the discussion and debate surrounding Nicole Sullivan's OOCSS the reasons, ultimately are more wider ranging than that.

The conversation so far

On one side we have a group of experienced CSS developers who say that it is advisable to use ID selectors as little as possible.

The reasons are generally simple:

The counter-argument, most eloquently outlined by the eminent Zeldman (don’t forget to read the comments as well), are equally simple. They roughly go as follows:

Both sides are actually correct, depending on the circumstance. However, in my own practice, I’ve landed firmly on the ‘no IDs in CSS’ side for reasons that go beyond those outlined by others.

So, these are my reasons. Feel free to ignore.

Collaboration

First of all, every complex project is a collaboration, even if you are working on it alone. The collaborator? Your future self.

Unless you have perfect memory there is no way you can pick up a stylesheet a year later and still retain a perfect mental model of the specificities of its selectors. If you were using IDs in the original, you are going to run into problems when you revisit the stylesheet a year later. I’ve run into this several times in my career.

IDs add complexity that make collaboration more problematic, even in teams of one.

Styles don’t need that much specificity

I agree with Zeldman that if you have an unique element, using an ID selector to apply its unique styles is not only preferable, it is the right way to do it.

The problem is that in most designs, unique – single element – styles are actually quite rare, generally only limited to positioning and modifying existing design elements. Most headers are composed of design features that are shared across many elements. The combination may be unique and the positioning of the header is unique, but that doesn’t leave much for the ID selector to do.

Also, using the ID selector in this context risks making it difficult for you to reuse those elements if it turns out they weren’t that unique. This happens all the time as you code up a website’s design.

So, even if you agree with Zeldman, that still means that you aren’t going to be using ID selectors much at all, mostly as singleton objects with a few, highly specific, properties.

IDs are over-loaded

Another thing many people misunderstand is that the idea is to avoid ID selectors, not to avoid IDs.

IDs used to only really be used by CSS and by anchors for links. Today, IDs play a central role in technologies as diverse as ARIA, scripting, links, and microdata. Everything is hooked into IDs.

Developing websites isn’t a waterfall-type process, where you first structure the markup, then the styles, before moving onto the scripting and accessibility. Making websites is an iterative process and when everything is too tightly coupled to IDs (or too tightly coupled, period), it’s very easy to break something in one area when you are working in another. Changing an ID when you’re working on the CSS can break the javascript and ARIA integration. You might notice the javascript breaking, but a lot of teams won’t notice their accessibility features breaking because they test them rarely.

Even if we don’t use ID selectors in our stylesheets our markup will still be littered with IDs because they are used by so many different layers of the web stack. CSS is the layer that is the most easily decoupled from IDs.

(RDFa Lite is unique among recent web technologies in how it approaches ID-like behaviour. It very sensibly proposes an analogous attribute called resource, enabling RDFa Lite markup to be integrated with a page’s markup without being tightly coupled and without inviting the fragility that comes with tight coupling.)

Loose versus tight coupling

One of the thing computing gurus such as Alan Kay have been harping on about since the late seventies is loose coupling. Systems that are built out of tightly coupled objects are more fragile and less dynamic than systems built out of loosely coupled elements. (Which is why ‘message-passing’ is one of the most important part of Alan Kay’s initial vision of object-oriented computing.)

IDs are already tightly coupled to so many of the web’s building blocks:

The only one technology that can, with great ease, be used with only loose coupling to the same, hard-coded, elements as all of the other layers are using, is CSS. By breaking down your styles into class-based building blocks and avoiding over-using both ID and element selectors your stylesheet can be more more flexible to use and more resistant to breaking as other people work on the site’s scripts and behaviour.

(Incidentally, I recommend Jonathan Snook’s Scalable and Modular Architecture for CSS for more information on this approach to CSS.)

There is freedom and flexibility in delegating ID use exclusively to links and behaviour.

Tightly coupled CSS makes everybody’s work more difficult. Loose coupling makes it easier.

The advice

This isn’t to say that ID selectors must be avoided by everybody everywhere. The above are my concerns for my projects and they may or may not be shared by others.

Overall, my advice can be broken down as follows:

As a general rule of thumb: if the only thing likely to refer to IDs is your CSS, go ahead and use ID selectors. If more than just CSS or links refer to the IDs, try to use ID selectors as little as possible. If you are working in a team, try to avoid them.