One of the key features in using Cascading Style Sheets is that you set a style then override it. And you can override just part of the display or all of it. Knowing how a browser chooses and applies your styles is invaluable knowledge.
In the previous post, you learned how you could reset the browser settings. Those settings override the user agent to provide you with a consistent look to start from. The point is that you can override the styles.
But how is the style chosen. What is the hierarchy? How should I be overriding the styles to get it to do what I want? How does the browser select which font/color/border to show?
Selectors and Media Types
First, the style is based on the selectors. See CSS3, jQuery Tutorial – Selectors Reference.
And the style that the browser chooses to render is also based on the @media rules, that you will learn about in a later post. Or, for those who want to start right away, see @media on Mozilla Developer Network. You will use @media to determine which stylesheet comes into play based on the size of the screen or print device that is being rendered.
Style Placement
There are several origins for your styles.
- Author. The author specifies style sheets for a source document according to the conventions of the document language. For instance, in HTML, style sheets may be included in the document or linked externally. (These are the ones you write, put into the header, in <style> tags, and inline your HTML.)
- User: The user may be able to specify style information for a particular document. For example, the user may specify a file that contains a style sheet or the user agent may provide an interface that generates a user style sheet (or behaves as if it did). CSS allows the reader (your user) of a document to apply style sheets to the document. These are called user style sheets. They become part of the cascade along with the author’s style sheets. You can try out a User Style Sheet in any of the browsers. See Cascading Style Sheets/User Style Sheets.
- User agent: Conforming user agents must apply a default style sheet (or behave as if they did). (I think of this as being how the browser renders the page. Different browsers (user agents) display their styles differently, which is why you override them with an author style sheet. See HTML5 Tip – Boilerplate.)
Cascading Order
Declarations apply if the associated selector matches the element in question and the target medium matches the media list on all @media rules containing the declaration and on all links on the path through which the style sheet was reached.
The CSS Specification for cascading provides a specific order of precedence:
Sort according to importance (normal or important) and origin (author, user, or user agent). In ascending order of precedence:
- user agent declarations
- user normal declarations
- author normal declarations
- author important declarations
- user important declarations
User normal declarations are styles that can be set by the user through a custom style sheet. These are read after the user agent declarations, so they will override the defaults set by the browser.
Author normal declarations are the declarations set by the website designer. A website usually uses at least one CSS file to define the way they want their website to look.
Specificity
And what if there are ties? Then rules with the same importance and origin by specificity of selector: more specific selectors will override more general ones. Pseudo-elements and pseudo-classes are counted as normal elements and classes, respectively. For example:
* {} /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */
li {} /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */
li:first-line {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
ul li {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
ul ol+li {} /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */
h1 + *[rel=up]{} /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */
ul ol li.red {} /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */
li.red.level {} /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */
#x34y {} /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */
style="" /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */
In this example, you can see that as your get more specific, the higher it will override the style. You can learn more about how it is calculated at Specifics on CSS Specificity.
Finally, sort by order specified: if two declarations have the same weight, origin and specificity, the latter specified wins. Declarations in imported style sheets are considered to be before any declarations in the style sheet itself.
!important
The important
keyword makes a declaration take precedence over normal declarations—those that are not tagged with the important
keyword. So “p { color: red ! important }” takes precedence over “p { color: green }”.
inherit
Inheritance is a mechanism that’s separate from the cascade: inheritance applies to the DOM (Document Object Model) tree, while the cascade deals with the style sheet rules. However, CSS properties set on an element via the cascade can be inherited by that element’s child elements.
For example, if a div
element has a font-size
of 20px
then, assuming that no other font-size
declarations have been explicitly defined, any children will also inherit that font-size
value.
Each property may also have a cascaded value of ‘inherit’, which means that, for a given element, the property takes the same specified value as the property for the element’s parent. The ‘inherit’ value can be used to enforce inheritance of values, and it can also be used on properties that are not normally inherited.
Debugging Styles
The easiest way to see this in action is to open your browser and press F12.
In IE, you can find the element, then see which selector was used to set the style.
In Chrome, you can see the cascading hierarchy as the browser sees it.
Changing Your User Agent
To be sure that your style sheets are performing the way you expect, you will want to try out the features in legacy browsers.
Resources
Assigning property values, Cascading, and Inheritance
Sample Code
Sample code is available in the DevDays GitHub repository. See https://github.com/devdays/html5-tutorials