Проблема специфичности CSS и ключевое слово !important
Не так давно какой-то пользователь создал в Twitter опрос о CSS специфичности. Большинство ответило на него неверно. В статье мы расскажем про CSS детальнее.
В этой статье мы проведем рефакторинг CSS-кода одного проекта с проблемами специфичности.
CSS специфичность
Определение
MDN Web Docs описывает специфичность, как: способ, с помощью которого браузеры определяют, какие значения свойств CSS наиболее соответствуют элементу и, следовательно, будут применены.
Правила
При определении того, какие именно свойства CSS нужно применить к элементу, браузер использует исходный порядок следования набора стилей CSS (то есть каскадность). Но это правило применимо лишь в случаях, когда CSS-селекторы обладают равной специфичностью. Что же произойдет, если специфичность одного селектора окажется выше специфичности другого?
В таком случае будет использоваться специфичность CSS-селектора. Чем выше его специфичность, тем больше шансов, что браузер применит именно это объявление CSS.
В примере выше оба CSS селектора нацелены на одинаковый HTML элемент – якорный тег. Для определения нужного правила браузер рассчитывает значения специфичности и проверяет, какое из них является наивысшим. В данном случае, высшее значение оказалось у первого селектора, поэтому к якорному тегу браузер применит именно его.
Важный момент: !important – это не CSS- селектор, а ключевое слово, которое принудительно переопределяет CSS-правила вне зависимости от значения специфичности, источника или исходного порядка следования селекторов. Несколько примеров использования:
- Временные решения (пример: вы временно заматываете изолентой подтекающую трубу);
- Переопределение встроенного стиля;
- Тестирование/отладка.
Несмотря на кажущуюся важность !important проблем от него намного больше, чем пользы. Со временем осложняется поддержка CSS и ухудшается читаемость таблицы стилей. Особенно от этого страдают те, кто работает/будет работать с кодом в будущем.
Проект
Пара слов о проекте, который будем рефакторить: это лендинг в стиле Netflix с использованием интерфейса MovieDB.

Таблица стилей
Основная цель – удалить ключевое слово “!important” из CSS-правил и провести рефакторинг кода, чтобы он применял только правила специфичности.
Ниже представлена таблица стилей проекта.
Мы видим, что чаще всего !important используется в разделе с медиа-запросами, описывающими стили, которые браузер применяет при ширине экрана меньше 750 пикселей.
Что же произойдет, если удалить ключевое слово !important из правил CSS, к которым оно применяется? У нас потеряется «верховод», который принудительно переопределяет CSS правила других селекторов для одного HTML-элемента. А конфликты между CSS-правилами браузер начнет проверять строго по таблице стилей.
При конфликтах приоритетности браузер руководствуется исходным порядком следования, специфичностью и важностью CSS-селектора. Если селекторы с конфликтными правилами обладают одинаковой специфичностью, то браузер учитывает исходный порядок следования и применяет CSS-правила селектора из таблицы сверху вниз. К сожалению, данная процедура не используется нашей таблице стилей.
Если CSS-селекторы с конфликтными правилами обладают разной специфичностью, то браузер выбирает правило селектора с наивысшей специфичностью. Этот принцип подходит нашей таблице стилей. CSS-селекторы в медиа-запросах обладают более низкой специфичностью, чем CSS-селекторы в основной части таблицы стилей.
Проблема определена. Пора переходить к ее решению!
Для начала найдем CSS-селекторы, соответствующие селекторам медиа-запросов.
Специфичность CSS-селекторов из основной части таблицы стилей выше. Поскольку правила специфичности имеют больший приоритет, чем правила исходного порядка следования, браузер применяет именно их.
Чтобы исправить ситуацию, необходимо увеличить значение специфичности CSS-селекторов в медиа-запросах. Тогда при одинаковой специфичности нескольких селекторов для одного HTML-элемента, браузер будет руководствоваться исходным порядком следования. Тогда при ширине экрана менее 750 пикселей будут применяться CSS-правила из медиа-запросов (которые расположены ниже по таблице стилей).
Конечный результат выглядит так:
Вот и все! Мы удалили все следы присутствия ключевого слова !important в стилях. Читаемость кода возрастает на глазах. После рефакторинга такую таблицу будет легче применять и поддерживать.
Заключение
Мы узнали о том, как именно браузеры выбирают CSS стилей по исходному порядку следования, специфичности и источникам селекторов. Познакомились с проблемами, возникающими при использовании !important в CSS, и научились сводить количество этих ключевых слов в коде к минимуму.
Больше не нужно добавлять !important для решения проблем – есть куда более достойные решения.
Сама концепция специфичности достаточно объемна. Но стоит разобраться в ней на практическом примере с подробной документацией, как вы научитесь применять эти знания в своих проектах.
Більше цікавих новин
Что нужно знать хорошему Frontend-разработчику
7 перспективных языков программирования
10 полезных Android и iOS библиотек
7 ошибок начинающих программистов
CSS important Not Working — and Fixes
The CSS !important rule can force a CSS snippet to work and act as a quick fix. This post will go through a few reasons why using the `!important` CSS keyword might not be working and their fixes.
May 5, 2022 | Read time 9 minutes
Table of contents
When styling elements with CSS, sometimes we can get frustrated that the styling is not applied and using the !important rule can force a CSS snippet to work. We can use this to force a CSS style. It sometimes work as a quick fix but not always.
This post will go through reasons why using the !important CSS keyword might not be working for you and their fixes.
The common reasons why !important is not working comes down to:
- You are using the wrong CSS selector and not targeting the correct element,
- You are using in animation @keyframes
- Using !important multiple times and having conflicts
What is the !important keyword?
The !important rule have been around since CSS1 specification in 1991 and allows the user to overrride browser specificity — this just means how a browser will decide which style to apply to each element.
The following diagram shows how browser will render HTML and display it to the user
Consider the following CSS style where we want to make all fonts in the <blockquote> to be italic:
Now if somehow the above is not working, we can use the !important rule like so:
CSS Specifity — which style gets applied!
CSS specifity just refers to which style the browser will apply to each element. There are quirks amongs browsers but most modern browsers like Chrome, Edge, Safari, etc generally follow the same rules.
- Browser Styles — each browser (chrome, safari, etc) comes with their own stylesheets. These default styles applied by your browser with the least precedence.
- User Styles — Custom styles created by the brower’s user.
- Author Styles — Styles created by the author/ creator of the website or page.
- !important Author Styles — author styles declared with important keyword.
- !important User Styles — user styles declared with important keyword.
- Inline Styles — inline styles will be given highest precedence and overwrite any styles previously.
- * — wildcard selector
- Type Selectors e.g <p> and Pseudo Elements e.g ::after
- Class Selectors e.g. .container , Attributes Selectors e.g. [target=”_blank”] and Pseudo Classes e.g. :hover .
- ID Selectors e.g. #app
- Inline styles
- !important — this will override any other previous styles
Fix 1 — !important not targetting correct element
The most common reason why using !important CSS rule is not working to style your element is that it is not targetting the correct element.
As an example, consider the following HTML and CSS
Now we can see that that text link <a> is not blue — even though we applied the !important rule to it. The reason this is failing is because we applied the rule to the wrong element. From the above, we have applied the color blue the list item elements and not link elements.
If we change the CSS to the following:
This will target the link <a> inside the list item <li> element
Fix 2 — !important used in @keyframes
One reason that the !important rule would not work is it only works on cascade properties. The cascade is how browers determine styles from different sources are combined to be applied for a specific element.
At rules such as the @keyframes do not participate in the cascade and therefore using !important will not work!
As example, consider the following HTML
We then want to animate this <div> using @keyframes as follows:
The above margin-left: 100px!important will not work, because @keyframes does not interact with the cascade and therefore the margin-left style of the <div> will not be overwritten by the value inside the 0%.
It will stay the same style as the inline style margin-left: 5px . If we remove the !important , then the margin-left: 100px; will be enforced!
Tip — dont use !important in @keyframes!
Fix 3 — !important used multiple times
The !important rule can be used to override an element’s styles, but it could be used to be overritten by itself. This can happen when you have multiple !important rules with the same selectors. Consider the following CSS style:
The bottom rule that specifies a border around the image will be applied because it has a higher specifity than the more generic top rule!
Tip — matching selectors that are declared lower in the CSS document will take precedence
One thing to keep in mind is that when you have multiple selectors that select the same element, the selector that is at the bottom of the CSS document will be applied! So for example, lets say we have the following paragraphs and their styles:
In the above, all <p> paragraph elements will have text of blue color! Even though we have two matching selectors, CSS style that is lower in the document will take precedence! To get around this and make the first paragraph color red, we can bump up the specifity declaring the following:
When should you use !important
Best practice is to avoid using !important and use specifity rules instead. This will make your CSS much cleaner and easier to manage. For example, too many important rules will make you loose track of which one is more important than the other (given the same selector).
- Used with user styles to apply the user custom CSS they want to apply for a webpage. This is because we have no control over the CSS that has been loaded.
- Dynamic styles set by JavaScript — to override styles applied by JS on the fly
Browser support
!important has been part of the CSS spec ever since CSS1 in 1991 and browser support for this is good for most modern browsers (chrome, safari, firefox, etc) and even older browsers such as IE (Internet explorer)
Summary
In this post I went over how CSS !important is not working — this can be a quick fix, but not recommended approach!
- Check that the !important property is applied correctly to the target element.
- Determine if the !important is used in at-rules such as @keyframes. This will not work because @keyframes will ignore the cascade
- Check that important is not used multiple times with your CSS — for example a higher specifity CSS declaration with !important applied will override anything that is less specific
About the Author
G’day! I am Kentaro a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.
My aim to share what I have learnt with you! (and to help me remember )
Чем перебить приоритет !important?
Возникла необходимость откорректировать размещенную на сайте форму обратной связи с клиентом, загружаемую скриптом партнерки. На CSS свойства некоторых дивов в ней установлен авторский приоритет !important, который, как известно, выше аналогичного пользовательского. По этой причине изменить свойства невозможно.
Подскажите, пожалуйста, как сделать пользовательский приоритет выше авторского.
- Регистрация: 15.09.2010
- Сообщений: 435
- Репутация: 100
- Webmoney BL:
?
через айфрем грузится или как?
а так можно вложенностью перебить, типа
.post__text-html h2 <
color:#000!important;
>
.nl .post__text-html h2 <
color:#7aa1bd!important;
>
CSS !important: Don’t Use It. Do This Instead
Though the option is available at our disposal, most experts consider the use of the !important declaration (or !important tag) as an anti-pattern. If you’ve spent any amount of time writing CSS, you have (or certainly will) come across a situation where your styles “aren’t working like they’re supposed to!”
In these cases, you might be tempted to add “!important” to the end of your style and be done with it. However, in this post, you’ll learn why this is rarely a good idea, and more importantly, how to simply avoid using !important in your CSS.
Skip Ahead:
There’s quite a bit to cover here. Go ahead and grab a cup of coffee and prepare for some code examples.
What does the !important tag actually do?
When you’re just starting with CSS, the !important tag seems like a secret weapon that you can pull out when styles aren’t working as expected. This situation occurs when you’re trying to override styles that are declared somewhere else in your CSS.
For example, let’s imagine you want to italicize everything that appears inside of <blockquote> elements.
And for some reason it’s not working as you would expect, so you add !important and everything is fine! It’s like magic!
What you’re actually doing in this case is increasing the specificity of everything inside blockquotes to an unreasonably high level.
By using !important, you’re essentially telling the browser that, under no circumstances should elements inside of blockquotes ever be anything other than italic.
This is a mistake. Let me explain.
Why you should avoid using !important in your CSS
Using the same scenario as above, let’s imagine 6 months go by and another developer on your team needs to “unitalicize” (for lack of a better word) blockquote text in some cases….such as citations. This is the first attempt:
Despite declaring a normal font-style specifically for the <cite> element, the text is still italicized.
Under normal circumstances, this would override the font-style that is set for the <cite> element, but it’s not working as expected!
The developer may even try adding a class or an ID to the <cite> element, only to discover that nothing will override the italicized text.
At this point, the only option is to add an !important tag to force the style to apply.
And the viscous cycle begins.
UX Engineer jobs
UX/UI and Frontend
Job Finder
The only thing that can override an !important tag is another !important tag. By using it one once, you potentially end up with a CSS file that is full of !important tags, which is not ideal.
If all your styles are !important, then none of your styles are important.
Fortunately, there is a better way to solve this dilemma. To get there, let’s go back to the basics and see how source order, inheritance, and specificity work together.
The source order rule
Source order is the first rule that determines which CSS style takes precedence. When overriding styles for a CSS selector, this rule should be taken into consideration first.
Source order refers to the order your styles are written. When you declare two different styles for the same selector, the declaration that appears last in your CSS file takes precedence.
The background property for the <blockquote> element is defined as yellow first and pink second. The result will be pink because of the source order rule.
What color is the blockquote?
There are three important things to point out in this example.
- Every new <blockquote> element that is added to the HTML will have a pink background.
- The second blockquote selector does not void the font-style property of the first since it’s never redefined. Instead, the styles accumulate.
- Since the <p> element is a child of the <blockquote> element, it is inheriting the font-style property that is applied to the blockquote.
The source order rule is our “weakest” option to override styles. If you’re stuck trying to understand why you’re styles aren’t being applied, check to see if the same styles are applied later in the CSS file first. If so, consider removing or rearranging the order of the last style declaration to fix the problem.
If you’re using multiple stylesheets, the order of your stylesheets will also affect the source order. Make sure any stylesheets that are referenced later in the HTML do not contain the same styles you’re trying to override.
The inherited property rule
Inheritance allows a child element to inherit styles from a parent element. When we need to override inherited styles, it can easily be done by targeting the child element in our CSS.
In the previous example we saw how source order determined the background color for the blockquote element. It’s safe to say that we can expect the same outcome if we apply a new value for the font-style property too.
The “normal” font-style that’s declared in the second blockquote selector cancels the “italic” font-style property in the first blockquote selector.
What happened to the text?
However, since the <p> element is merely inheriting the font-style property, we can easily override this style again by targeting the <p> element in our CSS.
What happened to the text?
Notice that the source order does not dictate the style in this case. Source order no longer matters because we are now targeting a different (and more specific) selector.
This is important to point out because it gives us insight into how specificity works. In this case, styles that are declared specifically for child elements will override the inherited styles of their parent elements.
Note: If you apply the text-decoration property to a parent element, targeting the child element with the same property will not override it. This is because text-decoration is not an inheritable property. It only seems like it is. You can read more about how this works here. You can also see a list of all inheritable CSS properties in this StackOverflow answer.
The specificity rule
Specificity rules take precedence over source order rules. We can apply various levels of specificity by using CSS selectors.
In the previous examples we targeted single HTML elements to declare our styles (blockquote and p). When used as selectors, HTML elements have the lowest specificity (with one exception, which is discussed later). This makes it easy to override element selectors by using a different selector.
With CSS we have the ability to “select” our HTML in a variety of ways. We can use the following selectors, or a combination of these selectors, to tell the browser specifically what we’re trying to do:
- *
- ids
- classes
- pseudo-classes
- attributes
- elements
- pseudo elements
Each selector carries a different “weight,” which helps browsers understand which styles should take precedence. In this example, we’ll override our <p> element styles by introducing a class.
First, let’s change our CSS up a bit and focus on overriding font colors.
As we know from the previous inheritance example, the font color assigned to the <p> element (light green) will override the inherited font color (white) of the blockquote.
What happened to the text?
Now, let’s add a “text” class and set a different value to its color property.
Also, let’s make a few changes to our HTML by
- adding a <span> element to see what happens
- adding a new <p> element with the “text” class applied
What happened to the text?
What happened to the text?
What happened to the text?
Let’s break down what is happening here (from top to bottom):
- A font color of “white” is applied to the <div> element. Since no font color is declared for a span selector, our <span> element inherits the white font color from the parent.
- A font color of “light green” is applied to the <p> element, which overrides the inherited “white” font color from the parent element.
- A font color of “yellow” is applied to the “text” class, which overrides the “light green” font color of the <p> element, which overrides the “white” font color of the parent element.
Makes sense right? After source order is taken into consideration it’s clear that priority goes from inherited styles to element selectors to class selectors.
It can get much more specific than that though. Let’s see how adding an ID to the mix will impact specificity.
First, let’s add an ID of “words” to our CSS and set the font color to light blue.
And we’ll add another <p> element with both the “text” class and the “words” ID applied.
The last <p> element now has 4 different font color properties being thrown at it. Which style will our new <p> element take?
You guessed it…the ID selector’s styles.
What happened to the text?
What happened to the text?
What happened to the text?
What happened to the text?
In this example, the ID font color overrides the class font color because it’s a more specific selector.
But wait. We’re still not done. You can still override your ID selectors too! Let’s duplicate our last <p> element and add an inline-style to it, setting the font color to pink.
Which results in this:
What happened to the text?
What happened to the text?
What happened to the text?
What happened to the text?
What happened to the text?
As you can see, the font color applied to the inline-styles overrides the ID selector’s font colors. Inline-styles are more specific than IDs.
And that’s when we get to the !important tag. The !important tag is the only way to override an inline style. To illustrate, let’s add an !important tag to the p selector styles and see what happens:
What happened to the text?
What happened to the text?
What happened to the text?
What happened to the text?
What happened to the text?
All of that specificity between our p selector and our inline-style is wasted! The only way we can override the color of our <p> element now is with additional !important tags that are applied later in our CSS.
The levels of specificity explained
As mentioned, each CSS selector carries a different “weight.” Browsers use to this weight to determine which styles should have priority. The weight is represented by a calculated specificity score between 0.0.0.0.0 and 1.0.0.0.0.
| Score | Selector |
|---|---|
| 0.0.0.0.0 | * |
| 0.0.0.0.1 | element or pseudo-element |
| 0.0.0.1.0 | class, pseudo-class, or data attribute |
| 0.0.1.0.0 | ID |
| 0.1.0.0.0 | Inline style |
| 1.0.0.0.0 | !important |
In the chart above, we can see the least specific (0.0.0.0.0) selector to most specific (1.0.0.0.0) selector.
Note: Technically, inline-styles and the !important declaration are not selectors, therefore you’ll usually see this score represented with only three placeholders decimals (i.e. 0.0.0). However, the chart above is still helpful to understand the levels of specificity.
With this in mind, it should be noted that you should use both ends of this spectrum with caution.
We’ve already discussed why you should avoid using !important tags, but in many cases the * (or select all) selector should be avoided as well for performance reasons.
This implies that there is kind of a “sweet spot” in the middle that you should try to stick too. As such, you’ll notice most stylesheets utilizing classes, pseudo-classes, and attributes more often than the other selector types.

The cheat sheet above can help you find a good starting point with CSS specificity. In general:
- The * selector should be avoided for performance reasons.
- Element selectors are useful for creating base styles.
- Classes are in the “sweet spot” of specificity
- IDs should be reserved for “unique” styles.
- Inline-styles should be reserved for rendering critical CSS.
- The !important tag should only be used when you’re absolutely sure about it.
But wait there’s more…
Applying incremental specificity
The specificity scores above illustrates how each selector represents a new “level” of specificity. If you can’t override a class by adding a new ID, then how are you supposed to override it? This is where incremental specificity comes in handy.
For example, let’s imagine we have the following HTML
The “text” class has already declared in your stylesheet.
Which looks like this:
You want to keep the underline and the italic styles, but you want to change the font color of the text inside the “module” div to red without affecting the navy font color inside the “box” div.
Because of the source order rule, we already know that doing something like this will change the text to red for all elements with the “text” class, which is not what we want.
However, since our “text” class is applied to a <span> element AND a <p> element, we can achieve incremental specificity by adding the p selector.
By targeting both an element and class, we’ve incrementally changed our specificity value from 0.0.0.1.0 to 0.0.0.1.1, which results in this:
However, if for some reason we decided to replace our <span> element with a <p> element, then we’re stuck with the same problem as before.
So how can we increase the specificity even more? We can target the “text” class within the “module” class instead.
This increases our specificity from 0.0.0.1.0 to 0.0.0.2.0 because we are now using two classes in our selector. Our styles are now back where we want them to be.
To drive the point home, let’s imagine that we have to create another <div> element with the “module” class. However, in this particular case we want to keep our navy font color.
Will result in this:
Option 1: We can reach up to the next selector (the ID) to achieve more specificity.
This will only target the text inside the content div and increase our specificity value to 0.0.1.2.0.
Option 2: We can introduce a “text-red” modifier class to the second <p> element.
This will keep our specificity value to 0.0.0.2.0, but still solve our problem.
Both options 1 and 2 will achieve the desired result:
Conclusion
As you can see, when you’re styles aren’t “working like they’re supposed to” you don’t have to resort the !important tag. You have other options. In fact, it’s strongly recommended that you avoid using the !important tag in the vast majority of cases.
Hopefully this guide has helped you understand how source order, inheritance, and specificity all play a role in determining how your styles work “behind the scenes.”
More importantly, hopefully this guide has helped you understand how to use these rules to your advantage when writing CSS.
If you found this post helpful, consider subscrib ing to UXE Weekly. You’ll receive the latest UX Engineer content directly to your inbox [almost] every week!