Year round learning for product, design and engineering professionals

In defense of the humble id attribute

Recently on my post about quoting HTML5 attributes, Paul Irish commented in passing

IDs are totally out of fashion now due to their high specificity so who cares

This idea has been floating around for a while.

Dave Gregory wrote Don’t use ID selectors in CSS almost exactly 3 years ago, observing the following.

  • The element is not re-usable on that page.
  • This is the beginning of a downward sprial into specificity.
  • Usually, IDs refer to something very specific, and abstracting would be tough.
  • Any performance gains picked up by using id, is negated by adding any other selector to the left fo that id.

The cat really got set among the pigeons when CSS Lint, a tool to help developers spot errors and adhere to good practice included a warning when your CSS uses id selectors.

One of CSS’s benefits is the ability to reuse style rules in multiple places. When you start out with an ID selector, you’re automatically limiting that style to a single element

Now, I’m far from the first person to have concerns with this recommendation. Matt Wilcox provided a detailed critique of a number of different practices he had concerns with.

In short: don’t blindly follow the crap these tools tell you. Chances are very high you’ll do yourself more harm than good, ending up with harder to maintain, bloated code, with nary a change in how fast your site feels.

The criticisms of the use of id are almost invariably about its shortcomings when used in CSS. But id is for more than just providing styling hooks.

I’ve got this crazy idea about developing for the web. These days it’s referred to as “content out”. The idea is that the content of the page drives the design. By marking up the page content as meaningfully as we can, we surface that content, and the associated functionality of the page. Then how we present this content is driven by the content.

In the semantically impoverished markup language that HTML has always been, ids allow us to say something about the content of a page. We can use it to uniquely identify an element on a page. The masthead. The site level navigation, the main content (yes I know about the proposed main element in HTML). Some things are unique within a page. At times it makes sense to identify these.

ids are for more than simply denoting unique elements within a page. As fragment identifiers, they allow us to link directly to part of a page (both within our own site, or to other sites entirely). They atomize web content, breaking down the monolithic page level structure of the web to arbitrarily small fragments.

They’re also obviously used with input (and related form) elements, to associate labels with these elements, and submit for content.

And of course, we can use the id to access elements in the DOM via JavaScript, either old school style using document.getElementsById, or new school style document.querySelectorAll('#idname').

So, the suggestion that we don’t use id attributes in any circumstance is contentious at best, I’d argue overly limiting, and in some cases impossible to follow.

Now, if we actually have id attributes on elements, why not use them with CSS selectors? The critique of using them with CSS is motivated by two primary concerns.

  • They’re overly specific.
  • They limit the reuse of CSS within a page.

Let’s look at each of these concerns in detail.

id selectors are overly specific

The id selector in CSS is very powerful. A single id alone will trump any real world combination of other selectors. So, the only way to over-ride style assigned using an id selector is to use more id selectors. In my own work over many years, I can’t actually recall this being an issue, but my work is typically done in very small teams that can work collaboratively, or alone. Where multiple developers work independently on a site I can see this as being more of an issue.

However, rather than the blanket rule applying to all situations, it should be applied in context. Where the over-specificity of ids may have an impact, such as where multiple independent teams work on CSS that might impact on a page, this rule may well make sense. In many other situations it strikes me as overly pedantic and restricting. If we can’t use id selectors, then anywhere we have an element with an id, we’ll also need a class attribute. Which in essence is adding class purely for stylistic purposes, contradicting the very well established practice of separating our semantics from our presentation.

But, if you’re really concerned about using an id selector due to its specificity, there’s the attribute selector. Attribute selectors allow us to select elements based on the presence, and value, of any attribute on an element. Since ids are attributes, attribute selectors apply equally to them as they do to class, href, alt or any other attribute. But, whereas id selectors have a very high specificity, attribute selectors all have the same specificity as the class selector.

For example, #main {} has a specificity of 100, while, *[id="main"] has a specificity of 10.

So, we can use the id attribute to select elements to style, but now the style assigned to an element via their id won’t trump that applied via class.

ids restrict reuse of style within a page

What about the second concern, that because ids are unique to a page, then if we create style for a particular element, we can’t reuse this style on the page. To me this is rather putting the cart ahead of the horse. My argument would be: if we have unique elements on a page, and if our appearance of these elements is a function of the unique element that they are, why not use their id? If a page has a unique header (as opposed to the sections of the page which may have their own header elements), and, as is likely, the h1 element of the page header appears differently from all the other h1 elements on the page (we’re using the HTML5 outlining approach, of course!), why wouldn’t we use the specific semantic aspects of the element to assign its style? If an element also plays a particular role, or belongs to a particular class of elements, then style that is a function of these aspects of the element should of course be assigned based on these characteristics (selectors of the form .classname, or [role=]).

Yes, styling via id restricts the reuse of style. At times that’s exactly what we want!

The politics of CSS

Recently, I had the privilege to hear Angus Croll present, The Politics of JavaScript. Luckily, you can see it too, as we’ve put the video of the presentation online. In it, Angus brings a critical eye to a number of “best practices” that he feels have over time been adopted unthinkingly. I have a lot of sympathy for this position (though Nicholas Zakas (co-developer it so happens of CSS Lint) presents a countervailing point that is also well worth the time reading).

Ultimately, Angus’s point is we should understand the rules, practices and guidelines, and adopt these, or not, with an understanding of the benefits they bring, and the costs that come with them.

I guess this post is really trying to bring some of that spirit to a particular guideline I’ve never been comfortable with, one which at least shouldn’t be adopted unthinkingly.

Perhaps my suggestion to Nicholas, and Nicole Sullivan, the original developers of CSS Lint would be to, where flagging the use of id selectors, suggest the alternative of using the attribute selector? To me it goes a long way to addressing the concern of the specificity of id selectors limiting their usefulness, while allowing for the ongoing use, and usefulness of a markup practice that’s been around, and widely used, for many a long year.

People mentioned in this post

Technologies mentioned in this post

delivering year round learning for front end and full stack professionals

Learn more about us

Web Directions South is the must-attend event of the year for anyone serious about web development

Phil Whitehouse General Manager, DT Sydney