« resources

Web Directions

Cascading Styles

a value for every property

workshops.oddbird.net/wd24/cascade/

Cmd/Ctr-K for Controls

An ordered list (cascade) of style sheets.

— Håkon Lie, Cascading HTML style sheets – a proposal

  • We’ve talked about the ordered list
  • or cascade of style sheets
  • And the way this…
css…
button          { background: gray; }
.action         { background: darkBlue; }
[type=“submit”] { background: darkGreen;
                  background: var(--submit, black); }
#send           { background: maroon; }
💥 Conflicts!
  • Inevitably leads to conflicts
  • And often, as developers,
  • We might think of those as being selector conflicts
  • But from the browser perspective,
  • It’s the individual declarations that we’re looking at
  • The selector is a bit of metadata attached to that declaration

For Browsers Every CSS Property
On Every HTML Element,
Must Have a Single Value

  • Before a browser can render the page
  • Every CSS property
  • on every HTML element
  • must have a single value

Every <button> Needs One Background-Color
& One Text Color
& One Border-Top-Left-Radius
& …

  • Every button needs
  • one text color,
  • one border-top-left-radius,
  • and so on

The Cascade (Process) Resolves Conflicts

removes extra values

  • What we call ‘the cascade’ now
  • is a browser process, an algorithm
  • merging our list of stylesheets
  • (‘cascading’ them together)
  • and resolving any conflicts between declarations
  • That process ensures we don’t have extra values

Inheritance… Provides Dynamic Defaults

fills in missing values

  • And then inheritance helps
  • Fill in some of the missing values
  • We’re not going to set all 500-some properties on every element!
  • So good defaults are essential,
  • (we’ve already seen some of that)
  • But there’s a whole separate step for it…
  1. Filtering
  2. Cascading (includes specificity)
  3. Defaulting (includes inheritance)
  4. Resolving
  5. Formatting
  6. Constraining
Value Processing (or ‘value resolution’)
  • After the cascade has finished.
  • Both are steps in a larger process called value resolution
  • Or value processing…
  1. Filtering (0+ declared values)
  2. Cascading (0|1 cascaded value)
  3. Defaulting (1 specified value)
  4. Resolving (1 computed value)
  5. Formatting (1 used value)
  6. Constraining (1 actual value)
  • Where each step gets us closer
  • to that actual rendered style on the page
  • Filtering to get all the relevant declarations
  • for a specific property on a specific element,
  • Cascading to resolve any conflicts between those declarations
  • Defaulting to fill in anything that wasn’t declared explicitly
  • And then several steps that help us resolve contextual & automatic values

Cascade & Inheritance Internal Browser Algorithms

  • On the one hand,
  • This is all internal logic, right?
  • Just an algorithm that browsers use…
Tina Turner as Aunty Entity in the Mad Max Thunderdome, with the law 'Two styles enter, one style leaves' in bold text
Necessary Browser Algorithms
  • to thunder-dome our declarations
  • And find a winner
The Crab Nebula photo: Webb Space Telescope
Description of Web Reality
  • Almost like the laws of physics…
  • A way of describing the universe around us,
  • The way the world works.
  • That’s all true, but also…
Yoda reaching out to control the force, surrounded by jungle swamp
Expressive Authoring Tools
  • tools provided to us, intentionally
  • part of the language,
  • designed for us to communicate…

Express… Purpose & Priority

  • At each step we get tools
  • to help us express purpose and priority
  • Of our hints and suggestions.
  1. Filtering

  2. Cascading
  3. Defaulting
  4. Resolving
  5. Formatting
  6. Constraining
Get a list of declared values (possibly empty)
  • That starts with filtering our stylesheets
  • To get all the relevant declarations
  • for a given property on a specific element

A Relevant Declaration

Cascading & Inheritance: Filtering

(Read it from the specification)

  1. In a stylesheet that applies to this document
    • (media attr)
  2. Not in a false conditional rule
    • (at-rules - media, supports, preferences, etc)
  3. In a selector that matches the HTML Element
  4. Is syntactically valid
Resilient HTML [present, debug]
  • Invalid CSS (like HTML) is discarded/ignored
  • Called ‘parse time’ validation
  • Not everything can be validated at this point
  • Useful, because we catch issues early
  • Before we discard other declarations
css…
.short { border: thin double; }
.long {
  border-top: thin double;
  border-left: thin double;
  border-bottom: thin double;
  border-right: thin double;
  border-image: none;
}
Expand Shorthands
  • This is also when we expand shorthand properties
  • Elements don’t have a border property
  • They have four border properties, and a border-image
  • Border is shorthand for setting all of them
css…
.short { border: thin double; }
.long {
  /* declared */
  border-top-width: thin;
  border-top-style: double;

  /* reset to 'initial' value */
  border-top-color: currentColor;
  border-image: none;
}
  • Four sides are also shorthand, including
  • The width, style, and color of each
  • Shorthands also reset the un-specified values
  • Initial value of border-color is currentColor
  • (We’ve set that implicitly)
  • Also border-image which is reset-only here

Use shorthand properties To Start Over

  • Shorthands are great for starting over
  • Reset everything
  • Build from the ground up
  • But they’re risky if…

Use longhand properties To Make Adjustments

  • You just want to make small adjustments
  • Long-hand properties are more precise
  • And leave everything else intact
  1. Filtering (list of declared values)
  2. Cascading

  3. Defaulting
  4. Resolving
  5. Formatting
  6. Constraining
Get a single cascaded value (possibly empty)
  • Once we have our list of declared values for a property
  • We know what conflicts exists
  • And we can use the cascade to resolve those conflicts
The Cascade (as a funnel) [present, debug]
  • The cascade itself has a 7 steps to it
  • 7 Questions we can ask to compare and discard declarations
  • Until we have a single winner
  • Starting with origins & importance, which we’ve discussed
  • Who requested it, and how much do they care?
Mechanical coin sorter on a table, with a ramp at the top and a small-to-large series of slots
  • We can think of each layer here as a coin sorter
  • Instead of measuring the size of a coin
  • Measuring the priority of each declaration
  • See which ones make it farthest
Same coin sorter, with all slots crossed off except for the largest one with coins in it, and an arrow pointing at those coins that says 'move on'
  • All we care about is the coins that made it the furthest
  • We can ignore any empty columns
  • And discard coins that didn’t make it quite as far
  • Those are gone from memory now!
  • But we still don’t have a single winner
Mechanical coin sorter duplicated multiple times in semi-transparent overlays
  • So we find another coin sorter, and we do it again
  • Over and over, until we have a single coin
  • Each time comparing different features
  • Not just size, but shape, width, metal, whatever
  • Ok, but not coins -
The Cascade (as a funnel) [present, debug]
  • So let’s keep going through them
  • We talked a bit about origins
  • But you can see there are a few we left out

For Intermediate Styles

in transitions and animations

  • For ‘intermediate’ or interpolated styles
  • Generated by animations & transitions

hotPink » teal

  • Take two colors (HotPink to Teal)
  • If we want to move between them,
  • The browser has to go through other colors…

hotPink
rgb(93 138 220) ?!
teal

  • (Depending on the color space we use)
  • Maybe we go through this bluish color
  • Along the way, that has to _override_both hotPink and teal
css…
button {
  background: teal;
  transition: background 1s;
}
button:hover { background: hotPink !important; }
  • For transitions,
  • The start and end values might come from any origin,
  • With any importance
  • The transition isn’t applied until after the cascade
  • So we’ve all had our say
  • We agree on the end points,
  • And we agree on transitioning between them
  1. 🖥 User Agent Defaults
  2. 👥 User Preferences
  3. 🎨 Author Styles
  4. ❗🎨 Author Important
  5. ❗👥 User Important
  6. ❗🖥 User Agent Important
  7. ➡️ Transitions
  • So the intermediate values have to override everything
  • Transitions are the most powerful ‘cascade origin’
css…
:target { animation: bg-change 3s ease-in both; }
@keyframes bg-change {
  from { background: pink; }
  to { background: cyan; }
}
  • Animations are a little different
  • Only the animation property is in the cascade
  • But keyframe declarations live outside the cascade
  1. 🖥 User Agent Defaults
  2. 👥 User Preferences
  3. 🎨 Author Styles
  4. 🏇🏽 Animations
  5. ❗🎨 Author Important
  6. ❗👥 User Important
  7. ❗🖥 User Agent Important
  8. ➡️ Transitions
  • So we still need a way to override specific parts of an animation
  • By slotting animated values just above the normal origins
  • Important styles become immune animation

Transition > ❗Important

Animate < ❗Important

Just to restate:

  • We can transition between important styles
  • And those transitional values will override everything else
  • But we cannot use keyframe animations to change important styles
  1. 🖥 User Agent Defaults
  2. 👥 User Preferences
  3. 💭 Non-CSS Presentational Hints
  4. 🎨 Author Styles
  5. 🏇🏽 Animations
  6. ❗🎨 Author Important
  7. ❗👥 User Important
  8. ❗🖥 User Agent Important
  9. ➡️ Transitions
  • And then there’s one… pseudo-origin?
  • For non-CSS presentational hints
html…
<img src="..." width="160px" height="90px" hidden>
<s>strikethrough</s>
Technically part of the author origin
  • This includes presentational HTML attributes like
  • width, or height, or hidden
  • Or the default styles of the strikethrough element
  • Since it’s a presentational element, not a semantic one
  • They’re a little weird, and in-between,
  • so spec doesn’t list them as their own origin,
  • But it does treat them like one, usually
Spock, and Spock with a goatee
  • Important styles always win,
  • But they also split us into two paths
  • An important mirror universe…
The Cascade (as a funnel) [present, debug]
  • We’ve seen that impact origins, reversing their priority
  • But they have a similar effect on several other steps as well
  • Including the next one,

🌗 (Shadow) Context

styling web components

  • Which is called Context in the cascade
  • It’s like a sub-‘origin’, but for shadow DOM styles
  • Styles that come from the shadow DOM
css…
/* shadow DOM styles */
:host(my-element) { outline: thin solid red; }
[part=title] { outline: thin dashed red; }
::slotted(span) { outline: thin dotted red; }

/* light DOM styles */
my-element { outline: thick solid green; }
my-element::part(title) { outline: thick dashed green; }
my-element > span { outline: thick dotted green; }
  • Since we generally can’t select Shadow DOM elements
  • From outside the shadow DOM,
  • There are only a few places where these conflicts can happen
  • Primarily light-DOM host element, exposed parts, and slotted elements
  • I’m not an expert with web components so I might have missed something
  • But those are the primary cases I know about

Shadow Styles Are Custom Defaults

similar to user agent origin

  • We can think of shadow DOM styles
  • As similar to browser defaults, from the user agent origin
  • We’re defining ‘custom elements’ and we can give them ‘custom defaults’
The Cascade (as a funnel) [present, debug]
  • Normal author styles from the page
  • will override those default shadow DOM styles
  • Unless we add !important to protect essential styles,
  • and then (again) the priority is reversed
  • Shadow styles can ‘take back’ priority when necessary

Again… Importance is Defensive

and reverses priority

  • Again, importance is defensive
  • Allowing component authors to protect essential styles
  • We’ll see this importance-reversal behavior again
  • in other steps of the cascade
Important Shadow Context [present, debug]

(demo if needed)

The Cascade (as a funnel) [present, debug]
  • Element attached (or inline) styles are next
  • They’re an exception to our importance reversal
  • They work the same on both tracks…
Element-Attached (Inline) Styles [present, debug]
  • Important styles can be used to override inline styles
  • But when both styles are normal, or both important
  • Then inline styles always win
The Cascade (as a funnel) [present, debug]
  • Remember, each of these steps is resolved
  • Before we move on to the next step
  • So if a single declaration wins after comparing
  • Origin, importance, context, or element attachment,
  • Then we never bother with layers or specificity and so on.

Cascade Layers

See details on the Web Features explorer
There’s also a polyfill
  • Cascade Layers are relatively new, but
  • Well supported across browsers,
  • For almost 3 years now
css…
@layer settings {}
@layer tools {}
@layer generic {}
@layer elements {}
@layer objects {}
@layer components {}
@layer overrides {}
  • They give us a way to organize our code
  • And help us manage the cascade
  • Or maybe more to the point…

Layers of Specificity

  • They can help us manage specificity
  • Because they come before specificity in the cascade
  • So the declaration in the highest layer wins
  • Before we bother to compare specificity
  • Inside the winning layer
Quick Layers Live Demo [present, debug]

demo:

  • Source order is fragile, layers are explicit
  • Specificity only matters inside a layer
  • Un-layered styles win by default
  • Layers stack in order
  • Define the order up front

Like Origins, ❗️important Layers Reverse

  • Like origins and context
  • Important layers are reversed
  1. Resets (weakest)
  2. Themes
  3. Components
  4. un-layered (strongest)
  • So if we have three layers
  • Each one overriding the previous

!important

  • And then we add important styles
  • Inside each layer
  1. Resets
  2. Themes
  3. Components
  4. un-layered
  5. ❗important un-layered
  6. ❗important Components
  7. ❗important Themes
  8. ❗important Resets
  • We now have six layer
  • With the important layers reversed
Kylo Ren and Rey
standing in front of an entire star war
with spaceships and lasers
and AT-AT walkers
  • Again, the goal is balance

Protect Styles From Future Layers

Prioritize -> Layers
Protect -> Importance

  • If we just want to override
  • Or manage priorities
  • That’s what layers are for
  • Importance only when essential
css…
@layer reset {
  [hidden] { display: none !important; }
}
  • So when I set the hidden attribute to display none
  • And add importance,
  • I can put that in my lowest layer,
  • I’ll call it the reset layer
  • And future, more powerful layers
  • won’t be able to override this declaration
  • It’s important, and so it’s protected.
  1. Resets
  2. Themes
  3. Components
  4. un-layered
  5. Inline Styles
  6. ❗important un-layered
  7. ❗important Components
  8. ❗important Themes
  9. ❗important Resets
  10. ❗important Inline Styles
  • While we’ve already covered inline styles,
  • And they aren’t technically ‘layers’ in the same way
  • It can be useful to understand how these two features of the cascade
  • Weave together somewhat,
  • With inline styles at the top of both
  • The normal and important layer order
The Cascade (as a funnel) [present, debug]
  • Which brings us to the most discussed
  • Maybe the most feared and hated part of the cascade…

🎯 Selector Specificity

Selectors (Level 4)
  • Selector specificity
  • This is where we compare
  • the selectors used for each declaration
css…
* { /* universal */ }
p { /* type */ }
.summary { /* attribute */ }
#call-to-action { /* id */ }
Simple Selectors
  • All simple selectors fall into four ‘categories’
  • Each with increasing priority in cascade…
css…
* { /* universal */ }
The universal (star) selector
  • The universal (star) selector
  • Alone in its category…
OddBird.net with red outlines around every element on the page
Similar to initial values - generic and universal
  • Selects all HTML elements
  • (but not pseudo-elements like before or after)
  • We can use this for extremely generic settings
  • Across every element on the page
css…
button, div, span {
  /* 'type' (element) */ }
::before, ::after, ::part() {
  /* 'pseudo-element' */ }
Type (element) selectors
  • Element & pseudo-elements
  • Are called ‘type’ selectors
OddBird.net with red outlines around every link on the page
Similar to browser defaults - provide a baseline
  • They are much more targeted, but still fairly broad
  • And (until recently) not something we could control
  • HTML defines what elements we have available to use
  • But still, these selectors can us establish
  • More customized defaults,
  • Similar to user agent styles
css…
.action, .summary {
  /* 'class' */ }
:hover, :user-invalid {
  /* 'pseudo-class' */ }
[type=“submit”] {
  /* 'attribute' */ }
Attribute selectors
  • Attribute selectors
  • (which include classes and pseudo-classes)
  • Select elements based on any attributes or exposed state
  • This is where we have the most control & flexibility
OddBird.net with red outlines around only the nav links which have a data-nav attribute
Establish reusable patterns
  • Great for defining reusable patterns
  • So they become the backbone of our design systems
css…
#send { /* 'id' */ }
ID selectors
  • Finally ID selectors
  • Valid ID’s are required to be unique on a page
OddBird.net with red outlines around only the logo
One-off overrides
  • Should only ever select one element per page
  • Extremely targeted/specific styles
css…
h1#page-title { /* … */ }
  • We can combine these simple parts
  • Into compound selectors…
Diagram of `p.summary:focus-within` with a solid pink arrow from the entire selector to a solid circle labeled subjects
  • Where every part referring to the same subject
  • Or describe relationships with combinators…
css…
p.summary a:hover { /* descendant */ }
p.summary > a:hover { /* child */ }
p.summary + a:hover { /* next */ }
p.summary ~ a:hover { /* future */ }
Complex Selectors (combined)
  • To form complex selectors
Diagram of `p.summary a:hover` with a dashed blue arrow from `p.summary` to an outer dashed circle labeled context, and a solid pink arrow from `a:hover` to an inner solid circle labeled subjects
  • Where there’s still only one subject (the far right compound)
  • But now different parts refer to different elements,
  • Providing context.
  • This is extremely powerful!
  • We can use selectors…
css…
h2:has(> button[aria-expanded="false"]) + div {
  display: none;
}
Disclosure Widgets by Adrian Roselli
  • to express fairly complex ideas
  • Read from right to left…
  • This selects a div that comes after an h2
  • (which has a button child, that is not expanded)
  • Look at all that information we’re communicating to the browser!

Specificity is a “Heuristic

a practical assumption that approximates the goal
  • But what we’re worried about now
  • Is the specificity of a selector in the cascade
  • And for this step the browser uses a heuristic
  • a practical assumption

More Explicit Selectors
are Likely
More Important

  • That narrowly targeted selectors like IDs
  • are likely more important than broad selectors like element types.
  • That makes some sense, right?
  • One-offs override reusable patterns,
  • which override element defaults,
  • which override global initial values?
css…
/* 1 IDs, 2 attributes, 2 element type */
/* specificity: 1,2,2 */
form#contact button[type='submit']:active {
  border-color: seaGreen;
}
  • To compare, we count up how many terms we used in each selector,
  • And which category those terms belong to
  • Here the border-color declaration has a selector
  • With 1 ID
  • 2 Attributes
  • 2 Element types
  • A specificity of 1, 2, 2
Our old coin sorter, with all slots crossed off except for the largest one with coins in it, and an arrow pointing at those coins that says 'move on'
  • The total isn’t what matters
  • We again compare the columns one at a time

Like Versioning [1,0,2] vs [0,3,2] vs [0,2,3]

  • Like software versions
  • We can look at the first number
  • That might give us a winner already

Move on when tied [0,3,2] vs [0,2,3]

  • We only have to look at the next column (attributes)
  • If there’s a tie in the first

Some ways to ‘Hack’ Specificity

css…
#example { /* [1,0,0] */ }
[id="example"] { /* [0,1,0] */ }
Reduce ID specificity
  • ID’s are often used in forms, aria-roles, etc
  • But sometimes ID specificity is too much for what we’re trying to do
  • Remember that IDs are attributes!
  • We can use an attribute selector instead,
  • Selecting the same element, with lower specificity
css…
.example { /* [0,1,0] */ }
.example.example.example { /* [0,3,0] */ }
Increase attribute/ID specificity
  • We can also increase the specificity
  • Of a class, attribute, or ID by repeating it
  • In a compound selectors (all strung together)
  • This changes specificity, without changing what we select

Some Newer Selectors Help Manage Specificity

  • There are also some new selectors
  • (and old selector tricks)
  • That we can use to manage specificity
  • Selector-by-selector

The `Is` Selector

See details on the Web Features explorer

The `Where` Selector

See details on the Web Features explorer

:is() and :where() Do The Same Selection

  • The :is() and :where() selectors
  • Can also be used to manipulate specificity
  • They always select the same things

:is() and :where() Have Different Specificity

:where() Removes Specificity

css…
/* nav a.active { 0,1,2 } */
nav a:where(.active) { /* 0,0,2 */ }
a:where(nav .active) { /* 0,0,1 */ }
*:where(nav a.active) { /* 0,0,0 */ }

:is() takes Highest Specificity

css…
:is(a, .b, #c .d) { /* 1,1,0 */ }
a:is(.b, #c .d) { /* 1,1,1 */ }
css…
a:where(#logo, .sponsor .logo) {
  /* specificity: 0,0,1 */
}

a:is(#logo, .sponsor .logo) {
  /* specificity: 1,0,1 */
}
Comparing Specificity

It doesn’t matter Which Selector Matches!

html…
<a class="sponsor logo">Still 1,0,1</a>
css…
a:is(#fakeID, .sponsor .logo) { /* … */ }
One external type, One internal ID

CSS Nesting

Also relies on :is() selector

:is() & :where() & Nesting [present, debug]

CSS Nesting

See details on the Web Features explorer
css…
.card {
  @media (width > 20em) {
    display: flex;
  }
}
We can nest at-rules
css…
ol, ul {
  > p { /* :is(ol, ul) > p */ }
  .sidebar & { /* .sidebar :is(ol, ul) */ }
}
Using :is() under the hood
css…
/* :is(button, .btn, #my-btn) */
button, .btn, #my-btn {
  &:focus,
  &:hover,
  &:active { /* 1,1,0 */ }
}
Specificity is different from Sass

While we’re here… :not() and :has()

:is() & :not() & :has() Use Same Specificity

Use :not() For Excluding Elements

(inside matches are removed from outside matches)

css…
/* (p) UNLESS (.warning)  */
p:not(.warning) { /* … */ }
Excluding v Overriding [present, debug]

Use :has() For Selecting Context

(we can move the subject!)

css…
form:has(:focus) { /* form with focus */ }
button:has(svg) { /* button with icon */ }
New :has() Selector
css…
form:focus-within { /* form with focus */ }
Shortcut with better support
css…
.card:has(> figure:first-child) { /* image card */ }
.card:not(:has(img)) { /* card without image */ }
input:has(+ .error) { /* input followed by error */ }
Allows Relative Selectors
Una Kravets [present, debug]
Has icon-text [present, debug]

The `Has` Selector

See details on the Web Features explorer
Light/dark with has [present, debug]
The Cascade (as a funnel) [present, debug]
  • After specificity,
  • Another new feature in the cascade

@scope

See details on the Web Features explorer
A grid of overlapping
'scope' columns (buttons, cards, logins)
and 'layer' rows
(default, theme, component).
Each scope crosses all layers,
and each layer crosses all scopes.

1. Avoid Naming Conflicts

(across large teams & projects)

2. By Expressing Membership

(through lower boundaries & proximity)

Scope Proximity

css…
.light-theme a { color: purple; }
.dark-theme a { color: plum; }
DOM Proximity
Scope proximity demo [present, debug]

@scope (<root>) { … }

Cascade & Inheritance, Level 6
css…
@scope (.light-theme) {
  a { /* similar to simple nesting… */ }
}
@scope (.dark-theme) {
  a { /* but the _closer_ scope root wins… */ }
}
Cascade & Inheritance, Level 6
Scope proximity demo [present, debug]

Scope Boundaries

css…
.title { /* global */ }
.post .title { /* nested */ }

.post__title { /* BEM */ }
Membership is distinct from ancestry
Media component with contents that are out of scope
A “donut scope” with lower boundaries
wireframe of a site, with multiple nested components
A “donut scope” with lower boundaries

Build-tools Provide Scoped Styles

BEM, CSS Modules, Vue, JSX, Stylable, etc

css…
.post__title { /* BEM */ }
.title[data-JKGHJ] { /* Vue */ }
Maintain uniqueness

@scope (<root>) to (<boundary>) {…}

Cascade & Inheritance, Level 6
css…
@scope (.media) to (.content) {
  img { /* only images that are "in scope" */ }
}
Cascade & Inheritance, Level 6
Visualizing scope [present, debug]
Scope boundary demo [present, debug]

Nested <style> Scopes

html…
<article>
  <style scoped>
    p { color: green; } 
  </style>
  <p>This paragraph will be green.</p>
</article>

<p>This paragraph won't!</p>
❌ This won’t work (yet)
html…
<article>
  <style>
    @scope { p { color: green; } }
  </style>
  <p>This paragraph will be green.</p>
</article>

<p>This paragraph won't!</p>
✅ This works

Different from CSS Nesting

Scope has… Defined Relationship

Always child or descendant

Scope… Doesn’t Add Specificity

Scope has… Lower Boundaries

css…
@scope (.block-name) to (.block-content) {
  .title { /* only inside the block! */ }
}
Use scope to narrow context (BEM blocks)
css…
button {
  &:hover { background: hotPink; }
  &[aria-pressed=true] { border: thick solid teal; }
  @media (width > 30em) { padding-inline: 1em; }
  & + & { border-inline-start: 1ch; }
}
Use nesting to provide variants (BEM modifiers) and other relationships

Different from Shadow-DOM Encapsulation

Diagram shows a widget with solid boundaries, which cannot be penetrated in either direction (global styles can't get in, widget styles can't get out)
Encapsulation is designed for isolated DOM widgets
Diagram shows a component with porous boundaries, all styles can penetrate, or establish their own lower boundaries
Scope is designed for a unified system
The Cascade (as a funnel) [present, debug]
  • The final step in the cascade

Order of Appearance

  • Order of appearance
  • Guarantees a single answer
css…
button {
  background: red;
  background: oklch(0.5 0.2 0);
}
  • That will come in handy when we talk about resilience, later
  • But here it just provides a failsafe
  • Only one declaration can come last
  • There will always be one
The Cascade (as a funnel) [present, debug]

And that’s the cascade, in 7 steps…

  1. Who requested it, and how much do they care?
  2. Does it come from the shadow DOM?
  3. Is it an inline style?
  4. What layer is it in?
  5. How specific is the selector?
  6. How close is the scope root?
  7. And which style was requested ‘last’?

Cascade output… Single (possibly empty)
Cascaded Value

for each property of each element

  • The input to the cascade
  • Was a list of declared values
  • (for each property on each element)
  • The output now
  • Is a single (possibly empty) cascaded value

There are Still Missing Values

Inheritance tomorrow!
  • Since some values are potentially empty
  • We need a process to fill them in!
  • We’ll talk about that tomorrow, along with…

And also… Custom Properties

a.k.a CSS Variables
  • Custom Properties (CSS variables)
  • Which can play a unique role in that process
  • That will start to move us out of theoretical physics
  • Into more applied use-cases and demos

The Cascade is Our Most Powerful Feature

  • Hopefully (today) a better understanding of cascade…
  • What it is, how it works
Kylo Ren and Rey
standing in front of an entire star war
with spaceships and lasers
and AT-AT walkers
  • Why it exists (to bring balance)
  • Where we fit into the larger process
Yoda reaching out to control the force, surrounded by jungle swamp
  • And ways we can use it
  • To write more expressive style rules
We're Not Alone, with browser logos, a guy in construction clothes carrying a laptop, and ET
  • As part of our style collaboration
  • With browsers, users,
  • and (hopefully) aliens
  • The cascade is what makes all of this possible.
« resources
Bring this workshop to your company.
Slide Controls

View:

Navigate slides using the arrow-keys.