Rachelle Rathbone

!important is Bad Mmkay

Why You Should Stop Using !important Everywhere

March 14, 2020

Well, it's not necessarily bad but, like any tool, it's important to know when to use !important.

As a project grows, so does the css that styles it. If not properly designed, it becomes all too easy to find yourself in a spot we've all been in before: you're declarations aren't working because the styles are being overridden by another declaration somewhere in your code. You could spend the time trying to find the root cause and updating the way styles are being applied in the application. Alternatively, you could simply add !important to the end of your declaration, letting the browser know this style must come before any other.

But what happens when the element or elements that's overriding your new styles already has the !important rule applied to it? Or what about when you've moved on to greener pastures and another developer sits in your seat and their new styles are being overridden by your declarations that have the !important rule peppered throughout? !important can lead to an ongoing battle that becomes harder and harder to beat so it's important to understand when to use it and what you should be doing to try and avoid stepping on your own, or another dev's, toes.

How a Browser Decides the Winning Style

When a browser renders elements in the DOM it applies the styles specified by the author (you and the other devs who worked on the project) and if no style is found for any given element, it will apply its own styles, known as user agent styles. The browser will also look for any !important rules applied by the author as these tell the browser that, well essentially, the style flagged with that rule is more important than any other styles for that element that the browser may happen to find.
This is known as the stylesheet origin - where the styles came from - and are applied by the browser in the following order:
  1. Author !important
  2. Author
  3. User agent
As a browser renders elements in the DOM, applying styles according to the order of stylesheet origin, it will also determine if multiple styles have been applied to the same element. When a browser finds an element with multiple declarations attempting to apply different styles, for example a h2 tag that has the declaration of font-weight: bold; in one place but font-weight:normal; in another, it will apply the rules of the cascade and specificity to determine which one wins.

The Cascade

In the above example, I've used the paragraph class name to target the paragraph element and set the color. Using the same class name over and over again in one file may not be something we'd ever really do but imagine if this were a huge project I was working on, with countless styling sheets and somewhere along the way, myself or another developer added a class name to an element, in this case paragraph that had already been used somewhere else in the project? Depending on how the styling sheets were structured, in this scenario my style would either be overridden by the one that was already in place or my style would override the other. Whatever declaration came last as the browser applied the cascade, would win. In this example, color: green is last meaning that any element with the paragraph tag would now be green whether that were my intention or not.

Specificity

In this next example, I've used a combination of tag-name, ID, and class name. We can see that the ID won this battle of specificity as our paragraph is blue. Even though, in terms of the cascade, the color red was the last style applied, an ID trumps a tag name when we are talking specificity. An ID should only be applied to on element, it is unique and tells the browser that this ruleset is of higher importance than any style currently applied in this application.

But what if I really wanted my paragraph to be red? In this simple example I'd simply remove the other styles but in large applications where certain styles are being applied to a large number of elements deleting styles isn't an option. Neither is editing the existing declarations as that would no doubt affect other parts of the application.

At this point, this is where some developers throw their hands in the air in frustration and, instead of trying to unravel the ball of yarn, take the easy path and apply !important.

Hooray! Problem is solved. Our job here is done. Let's pack up and things and go home!

But wait...

What happens in a few months from now when another developer is working on a different part of the application and has to use the paragraph class because they need most of the styles applied within the ruleset except they want the color to be blue? They use an ID as they want to target just one paragraph element and even make sure it's the last style in the stylesheets so they also have the cascade on their side. However, when they look in the browser they see the font color is still red.

Then they come up with a great idea. They too will apply the !important rule.

Perfect. That paragraph is now blue and as long as no one else uses that id, which they shouldn't because it should only be used on one element, everything should be okay, right? Right??

At this point we haven't got ourselves into too much water but you can see how this could eventually become problematic; If every time someone wanted to change the color of a paragraph they think of a way to overwrite that !important rule applied to the paragraph class. Devs could apply unique IDs to deal with the issue but sometimes you run into the issue where the same IDs start being used. Unintentionally of course, but hey, sometimes when there's thousands of lines of CSS someone might overlook that someone else has already used the paragraph ID in the application. They might scratch their head wondering why their style isn't being applied and then too come up with a great idea: apply the !important rule.

It's easy to imagine how, on a large project with multiple engineers, throwing the !important rule around willy-nilly can eventually lead you to dealing with a ball of yarn that's so twisted and tangled that you'd be better off throwing out that nasty ball and getting yourself a new one.

So What the Hell Do I Do?

When working on any application, developers should try to view !important as a tool to be used sparingly, if at all. Think of it as a special power that can only be used once. Would you waste this special ability the first time you ran into trouble? Or would you try to find an alternative solution so you could use your special power for when you absolutely, no-questions-asked, needed it because your life depended on it?

To avoid using your special power, try focusing on the rules of specificity to help you. When used effectively, you'll find that you may not ever find the need to apply the important rule.

Order of Specificity

When a browser is trying the determine the ultimate styling champion, it will look for the following:
  1. IDs: the element that has the most IDs will be victorious. If there's a tie or none of the competing elements have an ID the browser moves on.
  2. Classes: same deal as above. The element with the most classes takes home the trophy. In the event of a tie or lack of classes, the browser makes a final check.
  3. Tag names: finally, if elements with conflicting rules don't have any class names or ids, the browser will use tag names to determine the winner.

Now, you might be thinking, 'So if I start by using tag names to apply styles, then move to using class names when I need to be more specific, followed by IDs when I want to nail down something unique, I'll be in a good place right?' Not exactly. In addition to avoiding using !important you should also avoid using tag names to apply styles.

'Wait? What? You're telling me I should only use class names and IDs?!' Yes, that's exactly what I'm telling you.

When you start working on a brand new application and have the opportunity to think about how you will approach applying styles, take the time to do exactly that. Think about it carefully. An app that follows a solid styling methodology should never need to use tag names or apply !important. In fact, you may find you don't even need to use IDs. I've worked on several applications now that use nothing but class names to apply styling and, because of the way styling was implemented, I've never found myself in a situation where I was pulling my hair out over a declaration that was being overridden by some unseen force somewhere else in the application.

For those of you who don't have the luxury of starting anew and are deep in the hole of of tag names and !important, your job is a little harder but all is not lost. A tangled ball of yarn can be unwound, it just takes a little (perhaps a lot) more patience. It is usually best unravelled bit by bit until every knot and twist is resolved. Your task will require more work but it's not impossible. Commit to taking a new approach to applying styles for every new feature that is built and work on refactoring any existing feature when you work on it. Leave it better than you found it, as they say. Over time, as you and your teammates work together to clean things up, you'll eventually find yourself working with css that doesn't require an epic battle to get a declaration to stick.

If you're looking for some guidance in the realm of css styling methodologies, I recommend checking out BEM, Suit CSS, or Material UI.
...
© 2023, Rachelle Rathbone