33

This is a long shot, but is there a tool available that optimizes CSS selectors by removing unneeded specificity?

I find that when I write CSS, I deliberately make my selectors more specific than necessary to avoid conflicts and for quasi-documentation.

It would be great if there were a tool that could analyze a given group of rules, determine their "uniqueness" in terms of overlap with other rules, and then strip away any unnecessary specificity.

I can't even begin to imagine how a tool developer would approach all of the scenarios this would require, but I've been blown away by others' ingenuities in this area before and figured it was worth asking.

Update:

I've added a bounty to this question, and the more I think about it, the more I realize how valuable a CSS Specificity Filter would be.

For example, when working with Nested Rules/Selectors in Sass and LESS, excessive nesting is a common and well-known antipattern that can easily lead to overly specific selectors.

There's a good illustration of this in the excellent TutsPlus course Maintainable CSS with Sass and Compass:

body {
    div.container {
        p {
            a {
                color: purple;
            }
        }
    }
}

Sass will follow these nesting instructions and produce the following CSS output, raising no objection to any unneeded specificity:

body div.container p a {
    color: purple;
}

If a Specificity Filter did/does exist, however, it would create potential benefits for CSS developers:

  1. You could organize your stylesheets as a 1:1 mapping of the DOM, similar to what you see when you examine style rules in Firebug and Chrome Dev Tools. A smart editor/IDE could auto-populate styles for DOM elements with shared styles/classes. That redundancy would then, of course, be filtered out by the Specificity Filter/Optimizer.

  2. Stylesheets could have their structure pre-populated by a tool that scans the DOM and translates it to CSS selectors/rules. This means a developer would only need to update the HTML; the CSS "tree" would be kept in sync to reflect the current state of the DOM. A smart editor would let you jump to the CSS definition for an element/class for styling -- or even make its style rules visible in a separate panel.

In a way, this almost seems like a step backward - like a feature you'd find in Dreamweaver or WebAssist to help newbs learn CSS. But the basic idea of a CSS selector optimization tool seems like a no brainer, and the type of workflow automation I've described would be the logical next step -- and the catalyst would be the Specificity Filter.

I looked into some of the better-known CSS editors and web IDEs, but haven't found anything offering this type of functionality beyond targeting a single element and generating a selector for it.

Update 2: CSS Selector Performance

In response to Spliff's comment, here are two great articles on CSS selector performance:

Both agree that micro-optimizing CSS isn't worth the effort, but that over-qualified descendant selectors are "an efficiency disaster." I haven't benchmarked yet myself, but suspect that the kind of "DOM Mapping" approach I'm suggesting would cause a performance hit without an optimization step, either manual or automated.

Related Questions, Links, and Tools:

Points in CSS Specificity

Tool to See CSS Specificity

Tool for Cleaning Up CSS

Order by CSS Specificity

Top 5 Mistakes of Massive CSS

Google: Efficient CSS Selectors

Procssor

Clean CSS

CSS Tidy

Community
  • 1
  • 1
cantera
  • 21,869
  • 22
  • 87
  • 128
  • 2
    Of course, such a tool would need to inspect a DOM or a page to base the stylesheet on and make the right observations/assumptions (e.g. is there only going to be one `header` element with `id="pagehead"`? Will `aside` elements only occur within `section.sidebar`?). Otherwise, the only way to take specificity away from a selector *without fundamentally changing the meaning of the selector* is to remove repeated simple selectors, (e.g. `section > div.foo.foo:nth-of-type(odd)` becomes `section > div.foo:nth-of-type(odd)`). – BoltClock Aug 07 '12 at 17:29
  • 1
    @BoltClock: Also, if an ID is encountered, it's usually safe to eliminate anything before it. `html body div p#lorem span` can usually be shortened to `#lorem span` – Madara's Ghost Aug 07 '12 at 20:15
  • @Truth: That requires you to assume that the page is conformant (contains exactly one element with the ID) and will have such a structure, which may not always be the case. Once you have a DOM to look at you can pretty much assume anything and work away. That is the crucial part. *Maybe* you can at least remove the `html body` part of the selector. – BoltClock Aug 07 '12 at 20:17
  • 1
    Honestly, aside from following a few simple rules (don't add the element to a id/class selector, don't get crazy with nesting, etc.) I don't think it's worth worrying about. The [browser vendors are optimizing for this](http://calendar.perfplanet.com/2011/css-selector-performance-has-changed-for-the-better/) these days. – steveax Aug 09 '12 at 22:40
  • 1
    This is why I don't use preprocessors in the first place... – BoltClock Aug 10 '12 at 07:36
  • 1
    @Truth it also wouldnt necessarily work with dynamically generated HTML. In which case the actual element and nesting could depend on context and you may only want to apply the style to that ID if it is encountered in that specific context(elements around it). But the question itself has the same problem. Highly dynamic pages with generated HTML(be that server or client side) would make it hard to write such a filter that works reliably. – Stefan Aug 15 '12 at 17:48
  • Hmmm. Is there any scientific basis to your notion that CSS optimisation is actually important? I suspect that for a typical gzipped stylesheet this sort of optimisation will save less than a millisecond - even on an embedded device. You could shave 1px of the edge of every image and achieve 100x the optimisation. – SpliFF Aug 16 '12 at 06:36
  • Updating post with resources on CSS selector performance – cantera Aug 16 '12 at 07:30

4 Answers4

10

You could attempt to take a different approach, try to write your selectors as small (low specificity) as possible. and only make them more specific when needed. With that way of working you don't need a tool.

BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
Mark
  • 6,335
  • 1
  • 29
  • 49
  • [Writing efficient CSS selectors](http://csswizardry.com/2011/09/writing-efficient-css-selectors/) – Vladimir Starkov Aug 13 '12 at 16:43
  • I appreciate the reply, but the whole idea is to avoid this approach -- to have a tool that allows us to write CSS without having to think about specificity at all. The way it works now, we have to style DOM elements across multiple rules -- an optimization tool would allow us to handle all of an element's styles in one place. In my opinion it's a much more logical workflow; we've just become numb to the fact that CSS doesn't work this way. – cantera Aug 16 '12 at 07:58
  • CSS is a "situation-based" language (depending on HTML), there is no all-round CSS coding, otherwise everybody could do CSS styling. Specificity is so important, if someone don't understand specificity, he/she will for sure write bad CSS. I never felt the urge to have a tool. A tool can never output code like the way you want it to bee (aka mind-reading software). CSS (object oriented) is something you have to master, like any other web language. – Mark Aug 16 '12 at 08:44
2

We really can't do without specificity because it is the only thing that saves you when you have two or more rules colliding. Specificity brings sanity to the whole jumbled CSS rule, so it is more of a blessing than curse. Some of the stuff you talked about, like the CSS selector, can be done using Firefox/Firebug. I'm more disturbed by browser compatibility.

Jeromy French
  • 11,372
  • 13
  • 67
  • 119
omoabobade
  • 507
  • 5
  • 15
  • My thoughts exactly as I mentioned in my post too-- If you want to make sure you're writing good css, Firebug is great. – jos Aug 16 '12 at 16:24
  • 1
    Did you hit submit prematurely? Your last sentence is incomplete. – BoltClock Aug 18 '12 at 03:21
2

Just going to throw this out there-- it doesn't 'answer' your question,but it's a tool I like to spread the word about for people who do a lot of css programming: Firebug.

If you're not familiar with it, it's a tool for web browsers. You pull up your page once it's installed, right click and select 'Inspect Element.' It will show you all css affecting different elements on your page, and is useful for creating clean, precise css code. Also it makes it easier to see instant updates on what your page would look like with slight modifications. It will inform you of useless css code that's being overridden by other css code.

ALSO! Firebug now is available for almost all browsers. Not just Firefox. Personally, I'm partial to using it in Chrome.

jos
  • 391
  • 1
  • 9
1

Actually there's a way you can do this using HTML5 and CSS3. The standard technique is to specify elements using the HTML 5 attribute "data-" and then do CSS selection for this attribute. This isn't the purpose of the attributes, but you can customly specify some elements that you can use to even switch the theme of a site.

So, for example, you can end up creating your specificity filters manually in CSS, by specifying

<b data-specificity=2>test</b>

where data-specificity only matches to parents above.

UPDATE:

Alright, so for example, let's say you have a paragraph class, but you want to specify which parent, or how many parents the paragraph can inherit properties from. You would use rules for each potential parent that can be inherited from:

p[data-specificity="1"]{
    color:red;
    font-family:verdana;
    text-decoration:underline;
}
p[data-specificity="2"]{
    color:black;
    font-family:arial;
}
div.container > *[data-specificity="2"] {
    font-family:impact;
    color:blue;
    text-decoration:underline;
}

So these rules mean that any p tag which is a direct child of the div container and has specificity 2, is allowed to inherit properties from the div container. The blue color of the div gets inherited by the p with data-specificity 2.

Here's a JSFiddle where you can see this!

The idea is that like this, using HTML5, you can control exactly which elements are allowed to inherit which properties. It's a lot of extra code to write (for both child and parent elements) but you can use this to get rid of some unnecessary specificity

I've never actually seen anyone use this method in practice, I pretty much just cooked it up for you, but I think it could be very useful, what do you think ?

Cosmin Atanasiu
  • 2,092
  • 3
  • 16
  • 25
  • This is an interesting approach, thanks for replying. Unfortunately the quantity of non-semantic markup required would be a deal-killer for me, but this is a very creative solution to be sure. – cantera Aug 16 '12 at 21:43
  • well I can't put up a good answer in the next few hours, but if you extend the bounty date somehow, I'll post up a really clean solution with sample code ;) – Cosmin Atanasiu Aug 16 '12 at 21:43
  • Sure, I'm happy to re-up the bounty (assuming that's allowed). I'll add a comment here when I do so that it will appear in your inbox. – cantera Aug 16 '12 at 21:47
  • Sorry, updated my answer. When I wrote the answer I had something else in mind. I edited the answer accordingly – Cosmin Atanasiu Aug 19 '12 at 03:42