Inheritance & Specificity
How those two concepts actually work? Those two CSS concepts may be hard to grasp and look boring at first, but understanding them and knowing how to take advantage of them is important.
Talking about border-radius
and text-shadow
is a lot more fun; but specificity and inheritance are fundamental concepts that any person who wants to be good at CSS should understand. They will help you create clean, maintainable and flexible style sheets.
The notion of a “cascade” is at the heart of CSS (just look at its name). It ultimately determines which properties will modify a given element. The cascade is tied to three main concepts: importance, specificity and source order. The cascade follows these three steps to determine which properties to assign to an element. By the end of this process, the cascade has assigned a weight to each rule, and this weight determines which rule takes precedence, when more than one applies.
Importance
Style sheets can have a few different sources:
User agent For example, the browser’s default style sheet.
User Such as the user’s browser options.
Author This is the CSS provided by the page (whether inline, embedded or external)
By default, this is the order in which the different sources are processed, so the author’s rules will override those of the user and user agent, and so on.
There is also the !important
declaration to consider in the cascade. This declaration is used to balance the relative priority of user and author style sheets. While author style sheets take precedence over user ones, if a user rule has !important
applied to it, it will override even an author rule that also has !important
applied to it.
Knowing this, let’s look at the final order, in ascending order of importance:
User agent declarations,
User declarations,
Author declarations,
Author
!important
declarations,User
!important
declarations.
This flexibility in priority is key because it allows users to override styles that could hamper the accessibility of a website. (A user might want a larger font or a different color, for example.)
Specificity
Every CSS rule has a particular weight (as mentioned in the introduction), meaning it could be more or less important than the others or equally important. This weight defines which properties will be applied to an element when there are conflicting rules.
Upon assessing a rule’s importance, the cascade attributes a specificity to it; if one rule is more specific than another, it overrides it.
If two rules share the same weight, source and specificity, the later one is applied.
There are several ways to calculate a selector’s specificity.
The quickest way is to do the following. Add 1 for each element and pseudo-element (for example, :before
and :after
); add 10 for each attribute (for example, [type=”text”]
), class and pseudo-class (for example, :link
or :hover
); add 100 for each ID; and add 1000 for an inline style.
Let’s calculate the specificity of the following selectors using this method:
**p.note**
1 class + 1 element = 11**#sidebar p[lang="en"]**
1 ID + 1 attribute + 1 element = 111**body #main .post ul li:last-child**
1 ID + 1 class + 1 pseudo-class + 3 elements = 123
A similar method, described in the W3C’s specifications, is to start with a=0, b=0, c=0 and d=0 and replace the numbers accordingly:
a = 1 if the style is inline,
b = the number of IDs,
c = the number of attribute selectors, classes and pseudo-classes,
d = the number of element names and pseudo-elements.
Let’s calculate the specificity of another set of selectors:
**<p style="color:#000000;">**
a=1, b=0, c=0, d=0 → 1000**footer nav li:last-child**
a=0, b=0, c=1, d=3 → 0013**#sidebar input:not([type="submit"])**
a=0, b=1, c=1, d=1 → 0111 (Note that the negation pseudo-class doesn’t count, but the selector inside it does.)Remember that non-CSS presentational markup is attributed with a specificity of 0, which would apply, for example, to thefont
tag.Getting back to the
!important
declaration, keep in mind that using it on a shorthand property is the same as declaring all of its sub-properties as!important
(even if that would revert them to the default values).If you are using imported style sheets (
@import
) in your CSS, you have to declare them before all other rules. Thus, they would be considered as coming before all the other rules in the CSS file.Finally, if two selectors turn out to have the same specificity, the last one will override the previous one(s).
If not carefully considered, specificity can come back to haunt you and lead you to unwittingly transform your style sheets into a complex hierarchy of unnecessarily complicated rules.
You can follow a few guidelines to avoid major issues:
When starting work on the CSS, use generic selectors, and add specificity as you go along;
Using advanced selectors doesn’t mean using unnecessarily complicated ones;
Rely more on specificity than on the order of selectors, so that your style sheets are easier to edit and maintain (especially by others).
Inheritance
A succinct and clear explanation of inheritance is in the CSS3 Cascading and Inheritance module specifications (still in “Working draft” mode):
Inheritance is a way of propagating property values from parent elements to their children.
Some CSS properties are inherited by the children of elements by default. For example, if you set the body
tag of a page to a specific font, that font will be inherited by other elements, such as headings and paragraphs, without you having to specifically write as much. This is the magic of inheritance at work.
The CSS specification determines whether each property is inherited by default or not. Not all properties are inherited, but you can force ones to be by using the inherit
value.
HOW INHERITANCE WORKS
When an element inherits a value from its parent, it is inheriting its computed value. What does this mean? Every CSS property goes through a four-step process when its value is being determined
Specified value The user agent determines whether the value of the property comes from a style sheet, is inherited or should take its initial value.
Computed value The specified value is resolved to a computed value and exists even when a property doesn’t apply. The document doesn’t have to be laid out for the computed value to be determined.
Used value The used value takes the computed value and resolves any dependencies that can only be calculated after the document has been laid out (like percentages).
Actual value This is the value used for the final rendering, after any approximations have been applied (for example, converting a decimal to an integer).
If you look at any CSS property’s specification, you will see that it defines its initial (or default) value, the elements it applies to, its inheritance status and its computed value (among others). For example, the background-color
specification states the following:
Name: background-color Value: <color> Initial: transparent Applies to: all elements Inherited: no Percentages: N/A Media: visual Computed value: the computed color(s)
It can be confusing. So, what do we need to understand from all this? And why is it relevant to inheritance?
When an element inherits a value from its parent, it inherits its computed value. Because the computed value exists even if it isn’t specified in the style sheet, a property can be inherited even then: the initial value will be used. So, you can make use of inheritance even if the parent doesn’t have a specified property.
USING INHERITANCE
The most important thing to know about inheritance is how it works.
Imagine you had to specify the font-size
or font-family
of every element, instead of simply adding it to the body
element? That would cumbersome, which is why inheritance is so helpful.
Don’t break it by using the universal selector (*
) with properties that inherit by default. Bobby Jack wrote an interesting post about this on his Five-Minute Argument blog. You don’t have to remember all of the properties that inherit, but you will in time.
IE supports the inherit
value only from version 8, except for the direction
and visibility
properties
Last updated