slides.oddbird.net/variables/aea2104/

Beyond CSS Variables

slides.oddbird.net/variables/aea2104/

@ An Event Apart (Spring Summit)

Global Design Tokens

brand colors, sizes, fonts, etc…

hsl(322, 92%, 24%)

// origin
$best-color: hsl(322, 92%, 24%);

// meaning
$action: $best-color;

// usage
$link: $action;
$button: $action;

Don’t Do Anything

Until we apply them

button {
background-color: $button;
}

-webkit-property
-moz-property
--property

Define On Elements

// global
$best-color: hsl(322, 92%, 24%);
$action: $best-color;
$button: $action;
html {
--best-color: hsl(322, 92%, 24%);
--action: var(--best-color);
--button: var(--action);
}

Inherit By Default

$best-color: hsl(329.8 67.7% 57.5%);

html {
--action: #{$best-color};
}
$colors: (
'brand-blue': hsl(195, 52%, 31%),
'brand-orange': hsl(24, 100%, 62%),
'brand-pink': hsl(322, 92%, 24%),
);

html {
@for $name, $value in $colors {
--#{$name}: #{$value};
}
}

Then we can Polyfill CSS Variables!

Preprocessor are… Compiled (Server-Side)

button {
background-color: hsl(322, 92%, 24%);
}

Sass Variables are Static at Compilation

Responds to Devices

Responds to Browsers

Responds to User Preferences

Responds to Interactions

Responds to HTML Context

CSS Variables Need a New Mental Model

"CSS Custom Properties

…for Cascading Variables Module Level 1"

Custom Properties

Properties that we define

The Cascade Filters Targeted Values

when there are conflicts

p { color: black; }
p.error { color: red; }

Change values Based on State, Class, &c

Then Inheritance Fills in Missing Values

based on nearest target ancestor

html { color: green; }
p { /* color inherits */ }

Custom properties Capture a Value

Somewhere in the cascade

html { --action: red; }
main { --action: green; }
aside { --action: blue; }

And then… That Value Inherits

Through the DOM

button { background: var(--action); }

Define Nowhere

button {
background: var(--btn-color, teal);
}

var( --undefined, fallback )

Allows List Values

var(--my-font, Baskerville, Georgia, serif)

Nested Fallbacks

button {
background: var(--btn-color, var(--action, teal));
}

Font Stacks

font-family: Consolas, Menlo, 'Courier New', monospace;

Browser Fallbacks

button {
background: teal;
background: var(--btn-color, var(--action, teal));
}

Browser Fallbacks

html { background: red; }

@supports (--css: variables) {
html { background: green; }
}
  • [attr]Presence (even if empty)
  • [attr="..."]Exact match
  • [attr*="..."]Any match
  • [attr~="..."]Space-delimited (like classes)
  • [attr|="..."]Hyphen-delimited
  • [attr^="..."]Starts with…
  • [attr$="..."]Ends with…
  • [attr="..." i|s]Case sensativity

Defined Properties

For Changing State/Type

html {
@media (prefers-color-scheme: dark) {
--os-mode: -1;
}

@media (prefers-color-scheme: light) {
--os-mode: 1;
}
}
[data-colors='light'] {
--html-mode: 1;
}

[data-colors='dark'] {
--html-mode: -1;
}
[data-colors] {
--mode: var(
--html-mode, var(
--user-mode, var(
--os-mode, 1
)
)
);
}

Custom Properties Are Not Just Variables

(as we’ve known them)

Our medium is not done. Our medium is still going through radical changes.

– Jen Simmons, Designing with Grid

  • Global Tokens
  • Reusable Mixins
  • Pre-Compiled Functions

Custom Properties Dynamic & Responsive Styling

  • Contextual tokens
  • Dynamic Visualizations
  • Component Settings
  • User Interactions

The Web Is Responsive