by

The End of !important: Using Specificity Tricks to Trump Styles

Last week I was hit with a small challenge of fixing a snippet of code that fixed a problem with a third party application called Media Manager. It  does some pretty nifty things with videos — but it also injects a <style> into the <body>. Because it does that, I had a challenge in changing the dimensions of a video on the client-side. I first worked up a fix over there. Then I worked up a fix for the fix here. It involved a lot of attribute selector shenaniganery and ultimately, revelations about !important —including ways to avoid it at all costs.

What’s so bad about !important?

!important Hates the Cascade

There is a known problem that!important causes: It intentionally breaks the cascade.

If you didn’t know, cascading puts the C in CSS. So it’s kind of a bad idea to use !important…pretty much always. Smashing Magazine has my back on this.

!important Wasn’t Meant for Us

This is the bigger thing. If you read the specifications, you’ll see this:

CSS attempts to create a balance of power between author and user style sheets.

And !important is meant to balance the power:

However, for balance, an “!important” declaration…takes precedence over a normal declaration…This CSS feature improves accessibility of documents by giving users with special requirements (large fonts, color combinations, etc.) control over presentation.

When we use !important to battle our own stylesheets, it’s not so much about us winning, but the end-user losing.

Ignoring the Balance of Power

Let’s start with a typical scenario that we see where !important gets involved. It’s not usually about balance, but bickering.

First, let’s assume a snippet of HTML:

Howdy

An article title

So, you may have CSS that looks like this:

.heading{
color: #434343
}

Now, what we want is to change the style for the heading in the article, so we might do this:

.article .heading{
color: #333333;
}

But, let’s suppose someone else is playing in your stylesheet, and they modify your articleList:

.article .heading{
color: #333333;
}
/*a whole bunch of other CSS in the middle*/
.articleList .heading{
color:#434343;
}

Especially if you manage your CSS in small blocks, and you have a team of folks, it’s entirely possible that this happens. And because .articleList .heading happens later in the stylesheet, you’re styles are getting over written.

And so Begins the Bickering

There’s a few ways to handle this if you’re in a case where you can’t change the location of the CSS rule, or just tell the other CSS author to use a different selector. All these approaches involve using specificity as your weapon of choice.

Element Chains

You could chain an element to the final class. This is fine, so long as you can trust that the class will always be on that specific element. If you’re with a content management system, that’s a whole lot of trust, though:

.article h1.heading{
color: #333333;
}

The Parent Trap

Another option is to go up the element tree and add a parent selector. If you have a content management system, and you’re dealing with a piece of syndicatable (reusable) content, it’s hard to trust this approach.

.articleList .article .heading{
color: #333333;
}

Occam’s Selector

A third option is to prepend the two elements that probably will always be there. This is fine, so long as no one else gets the same idea:

body .article .heading{
color: #333333;
}
/*a whole bunch of other CSS in the middle*/
/*neat trick, I'll use it, too! */
html body .articleList .heading{
color:#434343;
}

The Nuclear Option

When you continue down this path, someone eventually decides to go nuclear and just ruin it for everyone:

html body .article .heading{
color: #333333 !important; 
}
/*a whole bunch of other CSS in the middle*/
/*neat trick, I'll use it, too! */
html body .articleList .heading{
color:#434343 !important; 
}

Alas, Babylon

All of the aforementioned approaches can actually be useful—so long as you’re not starting a Cold War of Specificity. But the Parent Trap and Element Chains create dependencies on markup — and markup could change. Occam’s Selector could be useful, but you’re blending specificity, and it’s limited. Prepending the body makes a specificity of 0,0,2,1 or 0,0,2,2 if you add the HTML.

But, there’s another set of methods that can keep us strictly dealing with classes, and remove a dependency on additional markup:

The Reagan Method

You can start by acting just a little bit crazy. Use the attribute selector — without a value. That’s right, use the class selector to target the element and then select on the fact that there’s a class. This was all I needed in my situation with Media Manager last week; I had two !importants and one needed to override the other.

.article .heading[class]{
color: #333333; 
}

The Roosevelt Approach

If you need to add some power to your crazy, you just double-down on that same chained attribute selector. Just chain the same thing again.

.article .heading[class][class]{
color: #333333; 
}

The Kennedy Technique

You’re not confined to just one type of attribute selector; branch out and try others, too. Just add a value this time. Yes, it’s crazy, but it works. Select on the fact that there’s a class, and then select on the fact that that class has a value of heading. After all, [class="heading"] is shorthand for .heading.

.article .heading[class][class="heading"]{
color: #333333; 
}

The Andrew Jackson

Not only did Andrew Jackson challenge people to duels regularly, he once beat his assassin nearly to death with his cane. Hopefully, no one actually tries to assassinate your selector. But if you do, you beat them to death with substring attribute selectors. If you go this route, you have near infinite ways to win on specificity. And you’re also insane.

For this example, I used the ^ which means “starts with”. You still have *(contains) and $(ends with) that you could chain.

.article .heading[class][class^="h"][class^="he"][class^="hea"][class^="head"][class^="headi"][class^="headin"][class^="heading"]{
color: #333333; 
}

The Big Idea

There are a few, legitimate reasons to use !important. If you follow the guidelines of the specs, it’s when you need to strike a balance between your styles and the end-users. Ideally, we only want to use it when someone else crossed the line, and we want to correct it.

But, if we’re not trying to fix a balance, and we just need to over write styles, let’s try a route that reads more like Alas, Babylon and less like On the Beach.

3 Comments


  1. //

    (Disclaimer: I had my morning coffee in the afternoon; YMMV)

    If you’re less against JS witchcraft than CSS sorcery (I’m on the fence), there’s this:

    $('style').each(function(){
    	$('head').prepend('');
    	$(this).remove();
    });
    

    1. //

      If you have control over the CMS, and you know that the style-block getting added is ridiculous and out of your control, then I’m definitely a fan of this approach.

      If I learned anything from Harry Potter novels, it’s that sorcery is generally a bad idea – and that you should solve the problem without doing things that involve tearing apart your soul (i.e. Seriously, don’t ever do the Andrew Jackson. Just…don’t)


Comments are closed.