Effficient CSS selectors

An exercise.

The fast CSS rules are saying, among other things, that a CSS selector is evaluated right to left, that the selector should be very specific, and that we should avoid descendant selector as much as possible.

Two things:

  • no IE6- support needed
  • fast CSS

made me come up with this practice code:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
  "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en"><head>

  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>Nested li</title>

  <style type="text/css">
  
    #some-list li, 
    #some-list .first-nested-list>span {
        border-bottom-width:1px;
        border-bottom-style:dotted;
        border-bottom-color:#5c8727;
      }

     #some-list .first-nested-list>span {
        display:block;
      }
      
    #some-list .first-nested-list {
        border:none;
      }
      
  </style>

</head><body>

  <ul id="some-list">
    <li>Item 1</li>
    <li class="first-nested-list">
      <span>Item 2</span>
      <ul>
        <li>Item 1</li>
        <li>Item2</li>
      </ul>
    </li>
    <li>Item 3</li>
  </ul>

</body></html>

As an exercise, it doesn’t matter if the difference in speed is high or low. It matters only if there is one. Also, are the fast CSS rules and the power of cascade nullifying each other?

In IE in quirks mode, the second main li: Item 2, is not underlined. The rest of the line is underlined, except the text Item 2.

And why would that be an issue - or did I miss a requirement somewhere? We don’t cater for IE in quirks mode these days otherwise we’d need to drop nearly everything :slight_smile:

According to the speed rules then this rule is very slow.


 #some-list .first-nested-list>span

As I understand it the quickest rule would be a simple class on the span and probably the best solution overall. Starting from right to left the class on the span is found first and matched in one go. No need to travel up any further.

Hi Paul,

This is exactly what I wanted to point out. I agree a class on span, along with a simpler selector would’ve been faster. But there is a catch with putting classes.

As a general rule for fast CSS, the selector should be as specific as possible, i.e. the id value being preferred over class and tag. Also, a simple selector is preferred over a compound selector.

It’s not possible to put classes and ids on every element, and it will defeat the purpose, since it will replace a tag with a class, most likely.

As a general rule for a compound selector, the left side should be as specific as possible.

If the left side of a compound selector is very specific, would that allow us to be less specific for the right side, to the tag level even, and still be in accordance with CSS fast rules?

About your example, what if someone forgot to put a DTD? :wink:
And my only purpose was to respond to your code like for a Turing test. :lol:

Ok :slight_smile:

From your example it would be quicker then to lose the ID as a match can be found from here.


.first-nested-list>span

Even though the id is unique it doesn’t come into play until after the above two have been reconciled (if my understanding is correct of course :)).

That would be my understanding too.

Yes, a match would be found for the .first-nested-list>span. Even more, putting a class on span would make for a further improvement, as you said. And maybe, by doing so, there are cases where that span having a class, that alone would suffice as a selector, making for a pretty fast CSS. But…

The further point I was outlining, it’s to assume we need both a tag (or a class), then a class (right to left).

If a span, in a li class first-nested-list, should be targeted differently then the other spans in the rest of the li class first-nested-list, I guess using an id rather than a tag for the third element in our compound selector would make it faster. Right?

However, this seems like an abuse of classes and ids. It looks a bit (or more) like the mess CMS are making.

I revert to my original question: making a fast CSS, using simpler selectors, using classes and ids to get rid of descendant selector, or other poor performance selectors, would this lead to a weaker CSS, by losing some of the power of cascade?

I see here a contradiction: generic selectors are what should make CSS practical. It seems that, for performance sake, we should be more specific in our selectors. And I’m not talking how much of a difference, this is subjective and arguable. I wonder if there is some difference you should account for, for bigger projects.

It would seem that for bigger projects, generic in cascade would be the logical answer. But technical reasons show otherwise. Again, this is to be discussed largely and theoretically, not attacking this or that.

Yes, I agree on those points :slight_smile:

There is a trade off between cleaner html and faster html.

Inefficient selectors could slow a large page down but most normal pages should be ok.

I see that some of the clever css3 stuff does slow browsers down quite considerably also.

https://developer.mozilla.org/en/Writing_Efficient_CSS
Simplifying CSS Selectors | High Performance Web Sites

I just realised we have strayed a bit off topic here.:slight_smile: It this secondary topic is of interest I can split it into it’s own thread for further discussion.

I’m familiar with the link from mozilla, but the second link sounds like a good one. Thanks. :slight_smile:

I guess a split would be in order.

I’ve also seen major performance difference between platforms. On Ubuntu, openSUSE, it seems FF handles CSS3 faster then on Windows.

It would be interesting to see if, this fast CSS, is in fact dependent on the UA. If what’s good in a browser, may be bad in another.

Mozilla says that descendant selector and tags in them are worst. Is it true for all UAs? I suspect it is.

Using classes and ids is not limitless if you want to keep the power of cascade at a reasonable level.

Using selectors like >, +, ~, nth to avoid descendant selector, along with existing classes and ids, would be an improvement or not?

How short does a selector has to be, if the left side of it is very specific?

It would be interesting to make some test cases to support an opinion or another.

Funny example here :slight_smile:

Steve Souders has a number of interesting observations here.

Reading the above links Paul gave (thanks again Paul, the google link I’ve known, but Souders’ one is pretty interesting, and along my thought line), I came to a strange thought: HTML5 tag diversity may actually be a good thing after all.

And it should be embraced, as it will reduce the number of classes and ids one would use in case it would wish to write fast CSS.

Instead of div this and div that, you actually have now aside, article, header, footer. A fragmentation, similar to the one a class would bring.

And the use of h1-h6 inside a section can be looked also at as a way to fragment endlessly probably repeating h2-h6 throughout a page.

Let’s face it, one h1 per page it’s more like an id than a tag. It’s seems like a waste of a tag, in CSS terms, of course.

These fragmentation help bring some more specificity at tag level, building a DOM having more variate elements, does making search easier and faster.

For example, instead of a big div array, we have smaller sets of headers, sections, footers, articles, asides. Specifying directly article instead of .article (from <div class=“article”…) is the first thought of what class values we may save.

This is funny. :slight_smile:

But, since UAs do the ingrate job of making any crappy page something at least usable, we could not ask at this moment in time, it should stop looking.

Consider the double equal id, or even multiple equal id values mistakenly set by an author in its page.

Yes, I suppose there are some benefits of having specific elements like that. :slight_smile: (Assuming of course that consistent styling is applied to those articles.)