As mentioned in Chapter 1, one of the important features of CSS is the ability for the user, browser, and web developer to all exert influence over the final output of the page. The user agent, the author, and the user can all three influence the output of the page. To dictate what property value “wins,” a multistep calculation is performed.
Inheritance
Inheritance is the mechanism by which CSS allows a value set on a parent element (such as <body>) to propagate to its descendants. This helps determine what value is used when no property is declared on an element property. The inherited value is determined by the computed value of a parent or ancestor. If none exists, the initial value, or default set by the browser, is used.
Cascading and Inheritance HTML
Cascading and Inheritance CSS
The body attribute has a text-align property value of justify. Styles are not set on paragraph attributes; however, the paragraphs are in fact justified. The paragraph text-align value is inherited from the body’s text-align property. Padding however is not inherited, which is why even though the body selector has a padding value of two rems, paragraphs, the image, links, and so on do not also have a 2rem padding value.
One of the main benefits of inheritance is that it prevents the need to write values for the same properties over and over again across different selectors helping with consistency of the styles and maintainability of the code.
In this example the color is also inherited, but the first letter of the first paragraph does not display in gray as set in the body selector, but in gold as set in the p:first-of-type::first-letter selector. The reason the first letter of the first paragraph is gold rather than gray is a question of specificity; p:first-of-type::first-letter is more specific than body.
Global Values
Inherit, unset , and initial are a little different from the rest of the property values available in CSS. These values are available on all properties and have the distinct difference of either resetting a value to default or to that of an ancestor rather than a new value. These values give you explicit control over how a property is inherited.
Exceptions HTML
Exceptions CSS
Unset
Unset works differently depending upon the property to which it is being assigned. If the value can be inherited from the parent, it will inherit; otherwise, it will set the property value to initial.
Initial
Inherit
As this example shows, we can force inheritance through the use of the inherit property, giving us direct control over the cascade.
Specificity
Selector Ranking
Category | Selectors |
---|---|
A | ID selectors |
B | Class selectors, attribute selectors, pseudo classes |
C | Type selectors, pseudo elements |
0 | Universal selector |
Calculating Specificity
Example Selector | A | B | C | Specificity |
---|---|---|---|---|
* | 0 | 0 | 0 | 0 |
button | 0 | 0 | 1 | 1 |
ul li | 0 | 0 | 2 | 2 |
button:not([type=submit]) | 0 | 1 | 1 | 1 1 |
a[href$=".pdf"]::before | 0 | 1 | 2 | 1 2 |
button.outline.bold | 0 | 2 | 1 | 2 1 |
button#submit | 1 | 0 | 1 | 1 0 1 |
Specificity plays an important role in determining which styles will get applied during the cascade.
Styles applied directly to the element in the HTML such as
<p style="margin-left: 10px">Lorem ipsum am met...</p>
are inline styles. They are the equivalent of adding property values directly in the DOM with the use of JavaScript. Inline styles are given a specificity of [1 0 0 0],3 which is higher than anything possible using normal selectors, as shown in Table 3-2. Inline styles are generally considered bad practice because they ignore inheritance and cascading. There are a few exceptions where they may be unavoidable though, including HTML e-mails.
Precedence
The order in which rules are applied matters. Directly targeted rules will always take precedence over rules which inherited from a parent or ancestor. If two rules with the same level of specificity are applied, the last one in order will be applied. This concept lies at the core of CSS and has since its inception, as indicated by its name “Cascading Style Sheets.”
The !important annotation is well known among CSS practitioners as both a powerful tool and a great liability. It’s sometimes used by web developers to force a style to take effect when nothing else seems to work. But did you know that the purpose of !important is actually to improve accessibility? Because important user declarations always have the highest precedence, it gives the user the final say on which properties and values are set when the page is rendered.
Order of Cascading4
Order | Origin | Importance | Precedence |
---|---|---|---|
1 | User Agent | Normal | 8 |
2 | User | Normal | 7 |
3 | Author | Normal | 6 |
4 | Animations | 5 | |
5 | Author | !important | 4 |
6 | User | !important | 3 |
7 | User Agent | !important | 2 |
8 | Transitions | 1 |
In cascading, the last item to be applied wins; therefore, transitions will win over user agent !important containing rules over user !important rules and so forth.
Cascading
Cascading represents the way properties and values from a variety of sources, at varying levels of precedence and specificity, come together to determine the final set of styles that will be rendered.
It is important to note that it is properties that are cascaded to elements, not rulesets. The final state of an element may include properties that were declared in many different rulesets.
- 1.
The declarations with the highest precedence are selected.
- 2.
The remaining declarations with the highest specificity are selected.
- 3.
When all other factors are equal, the declaration that appears last will be the one that is applied.
Value Processing
- 1.
First, all the declared values applied to an element are collected, for each property on each element. There may be 0 or many declared values applied to the element.
- 2.
Cascading yields the cascaded value. There is at most one cascaded value per property per element.
- 3.
Defaulting yields the specified value . Every element has exactly one specified value per property.
- 4.
Resolving value dependencies yields the computed value. Every element has exactly one computed value per property.
- 5.
Formatting the document yields the used value. An element only has a used value for a given property if that property applies to the element.
- 6.
Finally, the used value is transformed to the actual value based on constraints of the display environment. As with the used value, there may or may not be an actual value for a given property on an element.
Declared – These are all the values (0–many) that match the element and property under review.
Cascaded – This is the value (0–1) that is selected after processing the cascade.
Specified – This is the value of the cascade, if available, or the default value for the property and element. There will always be exactly one (1) specified value for each property and element.
Computed – The absolute value of the specified value which can then be inherited by child elements.
Used – This is the final value that the user agent uses for the layout of the document.
Actual – This is the value that is actually shown on a device, which may be adjusted from the used value due to device or environmental limitations.
The final actual values used for each property on each element are determined by a wide variety of factors external to your project code, including device, user agent or browser, user agent style sheet, and user-provided style sheet.
Summary
How HTML inline styles and !important annotations affect cascading
How to calculate the specificity for any given selector
The way properties are inherited within the DOM tree
In the following chapter, you will learn about the different options CSS provides for building fluid and responsive layouts that can adapt to variations in device and content.