CSS Precedence
Jakob Jenkov |
When multiple CSS rules target the same HTML elements, and those CSS rules set some of the same CSS properties, what styles end up being applied to the HTML element? In other words, which CSS rules take precedence?
CSS precedence is an issue that web designers and developers can spend long time fighting with. Understanding CSS precedence definitely makes the fight easier.
CSS Precedence Example
Before jumping into the CSS precedence rules, let us look at an example:
<head> <style> body { font-family: Arial; font-size: 14px; } p { font-size: 16px; } .logo { font-family: Helvetica; font-size : 20px; } </style> </head> <body> <div id="header"> <span class="logo">Super Co</span> </div> <div id="body"> <p> This is the body of my page </p> </div> </body>
This example contains three CSS rules. All three CSS rules set the CSS property font-size
,
and two of the CSS rules set the CSS property font-family
. The CSS rule for the
body
element is inherited by both the div
, span
and
p
element. Additionally, the span
element has a CSS rule targeting
it by its CSS class (.logo
), and the p
element has a CSS rule that targets
all p
elements. Which styles end up being applied to span
and p
elements?
CSS Precedence Rules
When the browser needs to resolve what styles to apply to a given HTML element, it uses a set of CSS precedence rules. Given these rules, the browser can determine what styles to apply. The rules are:
!important
after CSS properties.- Specificity of CSS rule selectors.
- Sequence of declaration.
I will explain what these rules mean in the following sections.
Note, that CSS precedence happens at CSS property level. Thus, if two CSS rules target the same HTML element, and the first CSS rule takes precedence over the second, then all CSS properties specified in the first CSS rule takes precedence over the CSS properties declared in the second rule. However, if the second CSS rule contains CSS properties that are not specified in the first CSS rule, then these are still applied. The CSS rules are combined - not overriding each other.
!Important
If you need a certain CSS property to take precedence over all other CSS rules setting the same
CSS property for the same HTML elements, you can add the instruction !important
after
the CSS property when you declare it. The !important
instruction has the highest precedence
of all precedence factors. Here is an !important
example:
<style> div { font-family: Arial; font-size: 16px !important; } .specialText { font-size: 18px; } </style> <div class="specialText"> This is special text. </div>
This example contains two CSS rules which both target the div
element.
Normally, a CSS rule with
CSS class selector has higher specificity than a CSS rule with an element selector, so normally the second
CSS rule (.specialText {...}
) would take precedence over the first CSS rule (div {...}
).
That means, that the .specialText
rule would set the font-size
of the div
element to 18px
.
However, since the div {...}
CSS rule contains the instruction
!important
after the font-size
CSS property, then that CSS property declaration
takes precedence over all other declarations without the !important
instruction targeting
the same HTML element.
Specificity of CSS Rule Selectors
Sometimes the browser cannot determine the CSS rule or property precedence based on the !important
instruction. Either because no CSS property declarations contain the !important
instruction,
or because multiple CSS property declaration contain the !important
instruction for the same
CSS property. In these cases the browser resorts to using the specificity of the CSS rule selectors
to determine what CSS properties take precedence.
The specificity of a CSS rule depends on its selector. The more specific the CSS selector is, the higher is the precedence of the CSS property declarations inside the CSS rule owning the selector.
In general terms, the more specifically (uniquely) a CSS selector targets an HTML element, the higher is its specificity.
The different CSS selector types has different specificity. By specificity is meant how specifically the CSS selector targets the element is selects. Here is a list of CSS selector specificity:
CSS Selector | Description |
---|---|
Inherited styles | Lowest specificity of all selectors - since an inherited style targets the element's parent, and not the HTML element itself. |
* | Lowest specificity of all directly targeted selectors |
element | Higher specificity than universal selector and inherited styles. |
attribute | Higher specificity than element selector |
class | Higher specificity than attribute, element and universal selectors. |
ID | Higher specificity than class selector. |
Combined selectors | Gets the specificity of the selectors combined. |
CSS properties set directly on element, inside style attribute. |
Stronger specificity than ID selector. |
Understanding specificity from this list alone is hard, so let me follow up with some examples. First, look at this HTML + CSS example:
<body> <style> body { font-size: 10px; } div { font-size: 11px; } [myattr] { font-size: 12px; } .aText { font-size: 13px; } #myId { font-size: 14px; } </style> <div > Text 1 </div> <div myattr > Text 2 </div> <div myattr class="aText" > Text 3 </div> <div myattr class="aText" id="myId" > Text 4 </div> </body>
This example contains 5 different CSS rules which all target one or more of the div
elements in the example.
The first CSS rule targets the body
element. The styles set for the body
element in this CSS rule are inherited by the div
elements. The CSS properties
set in this CSS rule will have the lowest precedence for the div
elements, as they
are not set directly on the div
elements, but rather on their parent element,
the body
element.
The second CSS rule targets the div
elements. This CSS rule is more specific
to div
elements that the styles inherited from the body
element.
The third CSS rule targets all HTML elements with an attribute named myattr
.
This is more specific than all div
elements. Thus, the div
element
with the myattr
attribute has this CSS rule applied. If you had set an attribute
value on the attribute selector, it would have been even more specific.
The fourth CSS rule targets all HTML elements with the CSS class named aText
.
The CSS class selector is more specific than a the div
element selector and [myattr]
attribute selector, so the
div
element with the CSS class aText
will have this CSS rule applied.
The fifth CSS rule targets the HTML element with the ID myId
. The ID selector
is more specific than the element selector, attribute selector and class selector, so the div
element with the
ID myId
has this CSS rule applied.
By now you should understand the specificity of the different selectors. But precedence can get more complicated still. When you combine CSS selector types their specificity is combined too. For instance, look at these CSS rules:
div { } div[myattr] div[myattr].aText { }
The first CSS rule is just the standard element selector. Nothing new here. The second selector, however, is a combination of the element selector and the attribute selector. This selector will be more specific than an attribute selector by itself. The third CSS rule combines an element selector, attribute selector and a class selector. This CSS selector is even more specific than a class selector by itself.
Once you start combining CSS selector types in your CSS rules you will need to scrutinize the precedence of those selectors more carefully, or make sure that they have no overlap in targeted elements, in order to achieve the desired styling.
Tweet | |
Jakob Jenkov |