slides.oddbird.net/rws/smashing/cascade/

Cascading & Inheritance

@ Smashing Online

CSS is a System For Applying Styles
to Elements

The proposed scheme provides a simple mapping between HTML elements and presentation hints.

– Håkon Lie

Inline with HTML

<button style=
background: rebeccapurple;
color: white;
font: inherit;
padding: 0 1em;
>
</button>
<button style=“background: rebeccapurple;  ></button>
<button style=“background: rebeccapurple; ></button>
<button style=“background: rebeccapurple; ></button>
<button style=“background: rebeccapurple; ></button>
<button style=“background: rebeccapurple; ></button>
<button style=“background: rebeccapurple; ></button>

Selector “Hooks”

button {
background: rebeccapurple;
}
<button></button>

Selectors come in Four Basic Categories

Universal *

* {}
<form>
<button></button>
</form>

Element Types

button {}
<button></button>

Classes & Attributes

.action {}
[type=“submit”] {}
<button class=“action” type=“submit”></button>

Unique IDs

#send {}
<button id=“send”></button>

We Can Combine Them

#send > button.action[type=“submit”] {}
<form id=“send”>
<button class=“action” type=“submit”></button>
</form>

We Can Stack Them

button {}
.action {
[type=“submit”]
{}
#send {}
<button id=“send” class=“action” type=“submit”></button>

These Are Powerful Features!

combine & layer selectors to convey meaning & intent

It’s also why We Need a 🌊 Cascade

button          { background: gray; }
.action { background: darkblue; }
[type=“submit”] { background: darkgreen;
background: var(--submit); }
#send { background: maroon; }
<button    style=“background: darkviolet;”
id=“send” class=“action” type=“submit”>
</button>

💥 Conflict!

[type=“submit”] { background: darkgreen; 
background: var(--submit); }
<button></button>

💥 OMG Mutliple background
On The Same <button>

For Browsers… Every Property
of Every Element
Must Have a Single Value

A <button> Needs One Background-Color
& One Text Color
& One Padding-Left
& One Margin-Bottom
&

The 🌊 Cascade Resolves 💥 Value Conflicts

  1. filtering -> declared values?
  2. cascading -> cascaded value?
  3. defaulting -> specified value
  4. resolving -> computed value
  5. formatting -> used value?
  6. constraining -> actual value?

For Each Element in the DOM

e.g. button or paragraph

And Each Available CSS Property

e.g. background-color or margin-left

1. Filtering… Are Values Explicitly Defined?

2. Cascading (if multiple)… Which Has the Most Weight?

3. Defaulting (if none)… Find a Fallback Value!

Either inheritance, or the property default

4–6 Calculate Final Values… Based on Context & Layout

How many px is 50% in this case?

We Often Talk About Selectors & 🎯 Specificity

Where We Have Control

button          { background: gray; }
.action { background: darkblue; }
[type=“submit”] { background: darkgreen;
background: var(--submit); }
#send { background: maroon; }

Each Selector has a Weight Based on How Specific It Is

Inline styles are explicit The Highest 🎯 Specificity

  1. Inline styles
  1. Inline styles
  2. Unique IDs
  1. Inline styles
  2. Unique IDs
  3. Reusable classes & attributes
  1. Inline styles
  2. Unique IDs
  3. Reusable classes & attributes
  4. Element types
  1. Inline styles
  2. Unique IDs
  3. Reusable classes & attributes
  4. Element types
  5. Universal *

Often Represented by Numbers Using Factors of 10

(but I don’t recommend it)

  • 1000 – Inline styles
  • 100 – Unique IDs
  • 10 – Reusable classes & attributes
  • 1 – Element types
  • 0 – Universal *
/* 1  +  10  +     10      + 0  == 21 */
button.action[type=“submit”] * {}

10*10!=100

By That Logic

/* 10 +  10 +  10 +  10 +  10 +  
10 + 10 + 10 + 10 + 10 = 100 */

.class.class.class.class.class
.class.class.class.class.class
{}

/* 100 = 100 */
#id {}

👎 Don’t Bother

small numbers are easier

More Like Versioning v3.9.5

More Like Versioning v3.10.5

More Like Versioning v3.11.5

More Like Versioning v3.462.5

More Like Versioning v3.462.5 < v4.0

Only the First Number Matters 2.5.1 or 1.12.2 or 1.3.42

Only the First Number Matters 2.5.1 or 1.12.2 or 1.3.42

Move on When Tied 1.12.2 or 1.3.42

Move on When Tied 1.12.2 or 1.3.42

Coin-sorter using different-sized column slots
Coin-sorter, with empty columns crossed out
Coin-sorter, all but the largest column crossed out

Ideally… A Layering System

From… Broad Patterns
to Specific Overrides

Triangle, point down, with layers:
settings, tools, generics, elements,
objects, components, overrides
inverted triange, with
range accross the top,
and specificity/explicitness
down the sides

Different Intents

  • universal/type » Reset / Normalizer
  • type/attr » Initial Defaults
  • attrs » Common Patterns
  • attrs » Page Layouts
  • attr > attr » Components
  • ID » Overrides

Some Limitations

👎 Too Few Layers

Use combinations!

👎 Only Classes & Attributes Are Customized AND Reusable

👎 Selector Double-Duty

As hooks & weights

👍 It’s Super Clever

👍 It’s Super Clever 👎 But It’s Way Too Clever

Anyway… 🌊 Cascade >>> 🎯 Specificity

Style sheets can be cascaded; the user/browser specifies initial preferences and hands the remaining influence over…

– Håkon Lie

… It provides author and reader with the same notation…

– Håkon Lie

The 🌊 Cascade starts with A List of Stylesheets

applied to the same document…

Potentially From Different 🗺 Origins

🖥 User Agent (Browser), 👥 User, or 🎨 Author

🖥 User Agent Styles
aka Browser Defaults

resource://gre-resources/

view
» page styles
» no style

all: revert Not all: initial

see also * { all: initial !important; }

👥 User Styles
aka Preferences

usually not CSS, but treated the same

(user preference demo)

🎨 Author Styles
aka Document Styles

absolutely everything we write

Stacked in Layers

  1. 🎨 Author
  2. 👥 User
  3. 🖥 User Agent

Like 🎯 Specificity Highest 🗺 Origin Wins

  1. 🎨 Author Styles
  2. 👥 User Preferences
  3. 🖥 User Agent Defaults

?!?!?

If conflicts arise the user should have the last word

– Håkon Lie

?!?!? What Gives!?

The Real Reason Forimportance

When anyone adds… !important

  1. ❗🖥 User Agent Important
  2. ❗👥 User Important
  3. ❗🎨 Author Important
  4. 🎨 Author Styles
  5. 👥 User Preferences
  6. 🖥 User Agent Defaults
  1. ❗🖥 User Agent Important
  2. ❗👥 User Important
  3. ❗🎨 Author Important
  4. 🎨 Author Styles
  5. 👥 User Preferences
  6. 🖥 User Agent Defaults
  1. ❗🖥 User Agent Important
  2. ❗👥 User Important
  3. ❗🎨 Author Important
  4. 🎨 Author Styles
  5. 👥 User Preferences
  6. 🖥 User Agent Defaults
  1. ❗🖥 User Agent Important
  2. ❗👥 User Important
  3. ❗🎨 Author Important
  4. 🎨 Author Styles
  5. 👥 User Preferences
  6. 🖥 User Agent Defaults

Feels Like Specificity

🐢layers all the way down…

A Few Special Origins

  1. ❗🖥 User Agent Important
  2. ❗👥 User Important
  3. ❗🎨 Author Important
  4. 🏇🏽 Animations
  5. 🎨 Author Styles
  6. 👥 User Preferences
  7. 🖥 User Agent Defaults
  1. 🎠 Transitions
  2. ❗🖥 User Agent Important
  3. ❗👥 User Important
  4. ❗🎨 Author Important
  5. 🏇🏽 Animations
  6. 🎨 Author Styles
  7. 👥 User Preferences
  8. 🖥 User Agent Defaults

Where the 🌊 Cascade Starts In Theory & Practice

  1. 🗺 Origin &importance
  2. 🎯 Selector Specificity
  3. ⏭ Source Order

The 🌊 Cascade Isn’t Only About Us

Because The Web Isn’t Only About Us

  1. 🗺 Origin &importance
    1. 🎠 Transitions
    2. ❗🖥 User Agent Important
    3. ❗👥 User Important
    4. ❗🎨 Author Important
    5. 🏇🏽 Animations
    6. 🎨 Author Styles
    7. 👥 User Preferences
    8. 🖥 User Agent Defaults
  2. 🎯 Selector Specificity
  3. ⏭ Source Order
  1. 🗺 Origin &importance
    1. 🎠 Transitions
    2. ❗🖥 User Agent Important
    3. ❗👥 User Important
    4. ❗🎨 Author Important
    5. 🏇🏽 Animations
    6. 🎨 Author Styles
    7. 👥 User Preferences
    8. 🖥 User Agent Defaults
  2. 🎯 Selector Specificity
  3. ⏭ Source Order
  1. Origin: 🎨 Author Styles
    1. 🎯 Selector Specificity
    2. ⏭ Source Order
  1. Origin: 🎨 Author Styles
    1. Inline Styles
    2. IDs
    3. Classes & Attributes
    4. Elements
    5. Universal *
  1. Origin: 🎨 Author Styles
    1. Inline Styles
    2. IDs
    3. Classes & Attributes
    4. Elements
    5. Universal *

If there are still options… The ⏭ Final Value Wins

  1. 🗺 Origin &importance
  2. 🎯 Selector Specificity
  3. ⏭ Source Order
  1. Origin: 🎨 Author Styles
    1. Specificity: Classes & Attributes
      1. ⏭ Source Order

The 🌊 Cascade Filters Out Extra Values

🧬 Inheritance Fills In Missing Values

  1. filtering -> declared values?
  2. cascading -> cascaded value?
  3. defaulting -> specified value
  4. resolving -> computed value
  5. formatting -> used value?
  6. constraining -> actual value?

Sometimes 🧬 Inheritance And Sometimes Initial Values

Generally… Text Styles Inherit
Box Styles Don’t

🌊 Cascade Is The Solid Architecture

🧬 Inheritance Is What’s Left Open

🧬 Inheritance Happens Last

🎯Specified Values Can Get There First

🧬 Inherited Values Don’t Care About Specificity

🧬 Inherited Values Only Care About Proximity

So We Filter Based On… 🗺 Where Sheets Come From

And… How ❗Important They Are

Then… What They 🎯 Target

And… Finally The ⏭ Order

Then… 🧬 Fill Any Gaps

A Wider 🌊 Cascade Allows More Nuance in Layering

Conventions like BEM Flatten 🌊 The Cascade

(every selector is a single class)

When Frameworks Often Automate Source Order

😬

Multiple Solutions

Authors Should Learn To Use The Full Cascade

👍 #IDs are Good

When they Express Meaning & Intent

👍 Nesting is Good

(We’ll come back to this in more detail)

W3C Should Update & Extend The Cascade

More 🎯 Nuance

e.g. :where()

“scoped” styles? Custom Elements
& Web Components

Custom Author Origins?

Triangle, point down, with layers:
settings, tools, generics, elements,
objects, components, overrides

¯\_(ツ)_/¯

The Cascade is Important

The Cascade is Useful

The Cascade is Not Going Away

Learn To Use It

@MiriSuzanne #ResilientWebSystems