Blog #10: Specificity War – When !important marks the start of a civil war
The story of how a few 'quick fix' CSS lines quietly turned our project into an unmaintainable minefield.
I once took over an old project that was 3 years old. The first time I opened the main CSS file, I almost fainted: there were over 500 !important keywords scattered everywhere.
When I tried to change the color of a button, I realized I couldn't do it the normal way. I wrote new CSS, but it wouldn't take. I increased the priority by adding a parent class, and it still wouldn't take. Finally, I realized I only had 2 choices: either write a selector as long as an epic poem or... add the 501st !important tag.
And that's exactly how a "Design System" dies—not because of missing documentation, but because of the chaos of Specificity.
1. The Arms Race: Who is higher than who?
CSS (Cascading Style Sheets) operates on a mechanism of hierarchy and priority.
- ID beats Class.
- Class beats Tag.
- And !important beats... everything.
The problem is, when someone in the team uses !important to quickly fix a UI bug, they've just set a "new threshold" for priority. The next person wanting to override that style is forced to use an even stronger !important. Just like that, the project falls into an endless arms race, where your CSS code is no longer interface design but a war for DOM control.
2. The Problem: "This button must be red at all costs!"
The trouble started one morning when a Designer requested to change the "Buy Now" button from blue to red for a holiday. A dev (who was in a hurry to go to lunch) noticed the .btn-primary class was being overwritten by a lot of external library CSS. Instead of finding out why, they wrote:
/* The "quick and easy" solution and a total disaster */
.buy-now-button {
background-color: red !important;
}
Three months later, we were making a new Theme for the app. We wanted all buttons to be purple. We changed the base variable color; all buttons turned purple... except for that "Buy Now" button, which stubbornly remained bright red.
It took us an hour to find that line of code. And because the project was so large, no one dared to remove the !important tag for fear it would break the UI on some other page we didn't know about.
3. The Process: Refactoring the Minefield
When the number of !important tags grows out of control, maintenance becomes a nightmare. Every time you change a pixel in the Header, an icon in the Footer magically disappears.
I had to conduct a major CSS cleanup. I didn't delete everything at once; instead, I used the CSS Specificity Graph tool to visualize the project's priorities. Looking at the chart, I saw towering "peaks"—those were places with too deeply nested selectors or !important.
Sustainable fix strategy:
- BEM (Block Element Modifier): Shifted everything to BEM naming to keep CSS priority at the level of a single Class.
- CSS Modules/Scoped CSS: Used modern tools to ensure that one component's CSS doesn't "invade" another's.
- Utility-first (Tailwind): One reason I love Tailwind is that it turns CSS into atomic classes with equal priority, completely eliminating the fight for specificity.
4. Trade-off: Cleanliness or Speed?
Refactoring CSS is an extremely underrated job. No boss is going to praise you: "Wow, you just deleted 500 !important tags, that's great!". They only care if the interface is broken.
Many will wonder: "Is it worth spending a whole week just to clean up CSS when new features aren't being built?". The answer is yes, if you don't want to spend an entire day 6 months from now just to find which selector is winning for a simple UI fix.
5. Junior vs. Senior: Self-restraint
A Junior developer sees !important as a miracle. "Code not run? Let me add !important. Oh, it works! Awesome!".
A Senior developer sees !important like an oil slick on the water. They will stop and ask: "Why isn't my CSS being applied? Where did I get the selector wrong? Is my HTML structure too messy?". They understand that every time they type !important, they are taking out a Technical Debt at a cutthroat interest rate.
Advice:
- Absolutely do not use
!importantfor normal interface logic. - Only use
!importantfor Utility classes (like .hidden, .mt-4) where you actually want them to override everything of a component. - Learn how to calculate Specificity points (e.g., Inline style = 1000, ID = 100, Class = 10, Tag = 1).
6. Lessons Learned
CSS is not simple; it's a science of managing priority.
- An
!importanttag is a signal of poor CSS structure. - Keep your selectors as short as possible. A depth of 3 levels is the red line limit.
- Use CSS Variables to manage Themes; don't use Classes to override colors.
Final advice: Become a disciplined developer. Don't let a moment of laziness today turn into an obsession for your colleagues (and yourself) tomorrow.
A beautiful interface is thanks to the Designer, but a sustainable interface is thanks to the discipline of the Frontend Engineer.
Series • Part 10 of 50