Dynamic CSS: Layouts & Beyond

@ Shift Remote

OddBird Consulting

Custom Apps, Design Systems, Training, & Refactors

1989… HTML

Markup Language

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

WWW Project

The first world wide website & graphic browser
NeXT computer with a worn-out sticker
Old IBM desktop
Modern desktops
A zillion different devices of all sizes (original)
Lineup of smart watches
Braille keyboard and headphones
Google Home, Amazon Echo, and Apple HomePod

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

WWW Project


The second browser, a text-only terminal

1994 (2000)… Cascading Style Sheets

An ordered list (cascade) of style sheets … can be referenced from the same document.

– Håkon Lie

The user/browser specifies initial preferences and hands the remaining influence over to the document [authors].

– Håkon Lie

[Authors] provide hints that the browser may or may not use.

– Håkon Lie

Declarative Syntax
!= Static Results

CSS is Dynamic & Responsive

Styling Unknown Content on an Unknown Canvas

Responsive Units

em & % » rem, ch, ex, vw, vh, vmax, vmin

currentColor Variable

Firefox 2006

calc() Function

Firefox 2011…

calc( 16px + 20% )

Combine Relative & Fixed Widths!

Custom Properties

Firefox 2014… Chrome/Safari 2016… Edge 2017

--aka: 'css variables';




--very: few restrictions;

var( --name )

var( --name , fallback)

Only One Fallback

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

Nested Fallbacks

var(--my-color, var(--other-color, pink))

Some Overlap With Sass Variables

$my-color: rebeccapurple;
--my-color: rebeccapurple;

Sass Variables Scope Without DOM Awareness

.example { 
$columns: 2;
.nested-class {
/* $columns == undefined */

Properties Inherit With DOM Awareness!

.example { 
--columns: 2;
.nested-class {
/* var(--columns) == 2 */

Media-Query Changes

@media (min-width: 30em) {
html {
$columns: 6; /* scope only */
--columns: 6; /* 30em+ in browsers! */

Custom Properties Not Just Variables

Use Both

Will It Change In The Browser?

Will It Change Depending on Context?

Keep NSYNC Properties From Variables

$gutter: 1rem;
html { --gutter: #{$gutter}; }

Custom Properties Inherit By Default

html {
--brand-color: hsl(330, 100%, 45%);
--action: var(--brand-color);

a {
color: var(--action);

Great for Global Design Tokens

Use :root With Caution

Higher specificity, and some unexpected results…

Reset Inheritance With Explicit Selectors

Declare Locally

.light-theme {
--text: black;

.dark-theme {
--text: white;

Declare Universally

* {
--grid-area: main;

Combine Both

[data-grid] * {
--grid-area: main;

Great for Components

Optional args… Leave Undefined

[data-btn] {
background: var(--btn-color, blue);

Custom Functions & Mixins

Dynamic Layouts

2017… CSS Grid

March 6-9: Firefox 52 & Chrome 57

Item Placement grid-column: <start> / <end>
grid-row: <start> / <end>

grid-column: span <count>


  'header          header         header' auto
'nav main aside' 1fr
'nav footer aside' auto
/ fit-content(20%) minmax(0, 1fr) 20em

Client Day Planner

Screenshot of schedule grid

Define the Day

<main style="
--day-start: 9,
--day-end: 18

Define the Events

<section style="
--event-start: 13,
--event-end: 14

CSS Animation

Set Index Prop To Offset Delay

<div style="--index: {{ loop.index }};">
[style*='--index'] {
animation-delay: calc(var(--index) * 50ms);

Create API For HTML Soft Patch

<div style="--ease: var(--in-out-back);">
[style*='--ease'] {
--in-quad: cubic-bezier(0.55, 0.085, 0.68, 0.53);
--out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--in-out-back: cubic-bezier(0.68, -0.55, 0.265, 1.55);
List of code dourses, all titled Learn X Language,
except the JavaScript course titled
Intro To JS
Krystal Campioni sprite animation
Sprite from Monster Slayer animation

Using Vue

'--src': show.sprite.src,
'--columns': show.sprite.columns,
'--rows': show.sprite.rows,
v-for="action in show.actions"
'--row': action.row,

Headshot of Ana Tudor

@anatudor Ana Tudor

CSS Tricks && CodePen