slides.oddbird.net/layers/jsheroes/

Cascading Layers of !mportance

slides.oddbird.net/layers/jsheroes/

@ JSHeroes, Romania
Product label for Cascade, with sheeting action for virtually spotless dishes - subtitled 'Use the Cascade'

It is required that HTML be a common language between all platforms

– WWW Project, HTML constraints

Sketch notes for Sandrina's talk Full Stack Forms - most of the image is faded out, with a scribbled circle around different platforms, different UI challenges

…This implies no device-specific markup, or anything which requires control over fonts or colors.

– WWW Project, HTML constraints

h1, h2, h3, h4 /* etc */ {
  font-weight: bold;
  font-size: something big I dunno; }
p { margin-block: 1em; }
a:link {
  color: blue;
  text-decoration: underline; }

Early web… All Styles are Universal

The same on every website

Controlled by… User Preferences
& Browser Choice

To understand CSS… Set Your Preferences

The web would have become a giant fax machine where pictures of text would be passed along.

– Håkon Lie, 2014 interview

… provide publishers with stylistic influence

– Håkon Lie

… provides author and reader with the same notation for specifying style …

– Håkon Lie

Safari settings panel, advanced tab, with a red scribble highlighting a style sheet option, with none selected by default.

CSS Declarations

/* property: value; */
color: blue;

CSS Selectors

p {
  background: white;
  color: mediumVioletRed;
}
<link rel="stylesheet" href="styles.css">

💥🙈⁉️💥

<button style="color: teal" type="submit"></button>
button { color: violet; }
[type=submit] { color: vibrant; }

On every html element
For every css property
We need exactly one value

Product label for Cascade, with sheeting action for virtually spotless dishes - subtitled 'Use the Cascade'

Cascade 🗺 Origins

  1. 🖥 User Agent (Browser) Defaults
  2. 👥 User Preferences

Cascade 🗺 Origins

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

If conflicts arise the user should have the last word

– Håkon Lie

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

Authors 👎🏼 Override Styles

We probably wrote ourselves

Users 👍🏼 Protect Styles

From future origins

Often Isolated

  1. 🎨 Author Styles
  2. ❗🎨 Author Important
  3. ❗…
  4. ❗…

Selectors exist to… Select Elements for Styling

Layers of Abstraction

#banner { /* single element */ }
.warning { /* class of elements */ }
p, li { /* type of element */ }
* { /* all of the elements */ }

Selectors make styling… More Efficient & Expressive

form:has(:invalid) [type="submit"] {}

In the Cascade Specificity is a Heuristic

How Specifically

Is a selector targeting elements

Assume we will… Start With Broad Generic Styles

Assume we will… Override With Targeted Styles

One Flexible Category

  1. Universal *
  2. Element types
  3. Reusable .classes & [attributes]
  4. Unique #IDs
.block .element.modifier { /* 3 */ }
.block__element--modifier { /* 1 */ }
/* don't touch */
.block__element--modifier {}

Even the best Heuristics Are Assumptions

@layer <name> { … }

Specificity is Contained

Higher layers win, with any selector

@layer default { /* least powerful */ }
@layer theme { /* … */ }
@layer components { /* more powerful */ }

/* unlayered styles: most powerful */
  • specificity & order
  • add one layer
  • add second layer
  • re-order layers
  • duplicate layer
  • add layer list
  • add nested layer
  • inspect with dev tools

@import url(…) layer(<name>);

@import url(system.css) layer(system);
/* system.css */
@layer theme {}
@layer components {}
@import url(system.css) layer(system);

@layer system.theme {}
@layer system.components {}

Getting Started

my recommendations, your milage may vary

Establish A Layer Order

/* first & easy to find */
@layer reset, design-system, components, utilities;
<style>/* keep this before linked styles */
@layer reset, design-system, components, utilities;
</style>
<link rel="stylesheet" href="">
<style>
@layer reset, defaults, theme, components, utilities;
@import url(reset.css) layer(reset);
@import url(defaults.css) layer(defaults);
@import url(theme.css) layer(theme);
@import url(components.css) layer(components);
@import url(utilities.css) layer(utilities);
</style>

Then Layer Dependencies

resets, design systems, frameworks, libraries…

Clearly define… Each Tool’s Priority

Clearly define… Tool-Specific Overrides

@import url(bootstrap.css) layer(bootstrap.core);

@layer bootstrap.overrides {
  /* anything here will override bootstrap */
}

For flexibility Layer Everything

Once we use un-layered styles, that’s as high as we can go

Only allow un-layered Prototyping & DeBugging

/* Vue example */
<template></template>
<script></script>

<style>
@layer components {
  /* all our component styles */
}
</style>

Good Tools Let Us Use CSS Features

(otherwise ‘tools’ become obstacle)

X Should Override Y
Because
‘Components’ Override ‘Defaults’

Then Un-Learn Specificity-Driven Selectors

The best selectors Don’t Need Naming Conventions

.form–-submit__invalid { /* ❌ */ }
form:has(:invalid) button[type=submit] { /* ✅ */ }

Bonus… Less Naming Things

.form–-submit__invalid { /* ❌ */ }
form:has(:invalid) button[type=submit] { /* ✅ */ }

Bonus… Encourage Proper HTML

.form–-submit__invalid { /* ❌ */ }
form:has(:invalid) button[type=submit] { /* ✅ */ }

Like Origins, ❗️important Layers Reverse

  1. @layer Resets
  2. @layer Themes
  3. @layer Components
  1. @layer Resets
  2. @layer Themes
  3. @layer Components
  4. ❗important Components
  5. ❗important Themes
  6. ❗important Resets

👎🏼 Override Styles

(that’s what layers are for)

👍🏼 Protect Styles

From future layers

@layer reset {
  [hidden] { display: none !important; }
}

Prioritize -> Layers
Protect -> Importance

Yoda leans on a walking stick among leaves

A Jedi uses the [Cascade] for knowledge and defense, never for attack.

– Yoda (almost)