I Don’t Do Django

but I love the template language

Prologue: Establishing Cred

Young OddBirds

OddBird now

Small Team, Outside Consulting

User Experience Design

HTML/CSS Implementation

(and open-source design-system tools)

OddBird’s Accoutrement

Abstract Design Patterns In Code

e.g. fonts, colors, sizes…

// Brand Colors
// ------------
$brand-colors: (
  'brand-orange': hsl(24, 100%, 39%),
  'brand-blue': hsl(195, 85%, 35%),
  'brand-pink': hsl(330, 85%, 48%),
  'action': 'brand-pink',
  'action-focus': 'action' ('darken': 15%),

Herman (alpha)

Automate Pattern Libraries

/// @preview color-palette

Herman color output



Another F*cking Grid System

It's only a flashback

Flashback: The History of Web Layout

Chapter 1: Ugh, Tables


(Lilly Ryan)

why do we do this to ourselves

Silly Dev,

Tables Are For Data


Limited Styling


Strict (non-linear) Markup


Accessibility Nightmare

Also An SEO/Legal Problem

(Lindsey Dragun)
Accessibility talk

Code is Communication

meaningful to humans and machines

Table Layouts Destroy Meaning

for both humans and machines…

Chapter 2: CSS Is Awesome

start with beautiful markup, then add presentation

and they lived happily ever after…

The End

CSS is Awesome

this is a feature!

don’t be fooled…

Declarative Syntax != Static Results

Dynamic Relationships

how is this going to change…?

…when the content changes?

…when the viewport changes?

…when the context changes?

Client Control Over Final Results

you’re not in a print shop any more…

All the devices

that’s, like, a small fraction of your audience?





Not Just WCAG Accessibility

(but also that)


for all kinds of not you

That’s The Job

Your Team, Please:




Chapter 3: Layout Concepts

Fix the Box Model

(IE got it right the first time)

Content-Box [Default]

total = width/height + borders + padding

content-box sizing


total = width/height

border-box sizing


Global Box-Sizing

* {
  box-sizing: border-box;


Fragile Box-Sizing

never inherit layout properties!

html {
  box-sizing: border-box;

* {
  box-sizing: inherit;

Avoid Tightly Coupled Elements

components respond to unexpected changes

Whenever You Can…

Go With The Flow

Chapter 4: Layout Techniques

[pre 2017]


Relative Positioning…

no effect on the flow, similar to transform: translate()

Position Relative


Absolute (or Fixed) Positioning…

removed from the flow entirely…

Position Absolute

relative to positioned ancestor (absolute) or viewport (fixed)…

Great For Overlays. Only.

off-canvas, drop-downs, tooltips, modals, etc…


CSS Floats

(not the worst hack…)

Floated images in text

Kinda Flows

This Makes Sense For Text-Wrap

Floated images in text

You’ll Need a ClearFix (Hack)

apply to any container element…

// "Micro" Clearfix Mixin
@mixin clearfix {
  &:after {
    clear: both;
    content: ' ';
    display: table;
// "Micro" Clearfix Class
.clearfix::after {
    clear: both;
    content: ' ';
    display: table;

display: flow-root

the new clearfix alternative

Poor browser support

Overflow: Hidden

(Hack) for fluid columns, and clearing containers

(be careful)


Flexible Markup & Nesting!

  <div class="float">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Perspiciatis laudantium ea tenetur quas incidunt. Voluptatibus veritatis, rerum vitae illum, recusandae quis. Recusandae quisquam sunt id, eius debitis quos animi hic.
    <div class="next">Next! (overflow hack)</div>
    <div> <!-- They all collapse! -->
                  <div class="last">Last! (floating)</div>


Always Define The Width

floats aren’t very smart about context…


Sub-Pixel Rounding?

What is 25% of 50px… in 2008?

Old subpixel rounding diagram

demo by John Resig



invasive and confusing hacks required


Display: Table?

no margins, use border-padding



kinda like floats+display-table, but not a hack


So Many Options

managing the distribution of extra space

.container {
  align-items: stretch; /* equal-height! */
  display: flex;
  justify-content: space-between; /* change the distribution */

.another {
  align-items: center; /* vertical-centering! */
  display: flex;
  flex-direction: row-reverse; /* change the direction of flow */
  order: 2; /* re-order the DOM */


Flexing is Magic

play with these relationships…

.element {
  flex-grow: 1; /* ability to grow in relation to siblings */
  flex-shrink: 5; /* ability to shrink in relation to siblings */
  flex-basis: 33em; /* starting, optimal size */

flex-basis defaults to width

(which defaults to auto)


Still A One-Dimensional Flow

(with line-wrapping options)


Nesting Matters Too Much

We need display: contents


Poor Performance for Page Layouts

Chapter 5: Grid Systems, A Historic Detour

mostly using floats

12 Equal Columns

grid demo


Provides Consistency


Enforces Consistency


Shared CSS Hacks

2007: Blueprint CSS

fixed width, margin gutters on the right…

.container {
  width: 950px;
  margin: 0 auto;

/* Sets up basic grid floating and margin. */
.span-1, .span-2, .span-3, 
.span-4, .span-5, .span-6 {
  float: left;
  margin-right: 10px;
/* The last column in a row needs this class. */
.last { margin-right: 0; }

/* Use these classes to set the width of a column. */
.span-1 {width: 30px;}
.span-2 {width: 70px;}
.span-3 {width: 110px;}
.span-4 {width: 150px;}
.span-5 {width: 190px;}
.span-6 {width: 230px;}

(Olav Bjorkoy)

Columns & [Margin] Gutters

grid demo

Spanning Columns

span demo

Remove The Last Gutter

grid demo

(you can flip this model with left margins, removed on the first column)

<article class="column col6of12 last">Article</article>

Classes Are The API


Clear APIs Are Good


Developers Can Ignore CSS


Developers Ignore CSS

Best For Massive Codebase

over long periods, with too many developers, and little communication

Are You MailForce or InstaFace?

2009: Object Oriented CSS

simple fractions, no gutters

/* CSS Grids */
/* **************** GRIDS ***************** */
.line, .lastunit {overflow: hidden; _overflow: visible; zoom:1;width:auto !important;}
.size1on2{width:50%;_width:49.9% !important;}
.size1on3{width:33.33333%;_width:33.25% !important;}
.size2on3{width:66.66666%;_width:66.65% !important;}
.size1on4{width:25%;_width:24.95% !important;}
.size3on4{width:75%;_width:74.95% !important;}
.size1on5{width:20%;_width:19.95% !important;}
.size2on5{width:40%;_width:39.95% !important;}
.size3on5{width:60%;_width:59.95% !important;}
.size4on5{width:80%;_width:79.95% !important;}
.lastunit {float:none;_float:right;}

(Nicole Sullivan)

No Margin Gutters

technically, no grid

inside demo

<article class="unit size1on2">Article</article>

2010: 960 Grids

gutters split left and right

.container_16 {
  margin-left: auto;
  margin-right: auto;
  width: 960px;
.grid_1, .grid_2, .grid_3,
.grid_4, .grid_5, .grid_6 {
  display: inline;
  float: left;
  margin-left: 10px;
  margin-right: 10px;

.container_12 .grid_1 {
  width: 60px;

.container_12 .grid_2 {
  width: 140px;

(Nathan Smith)

Split [Margin] Gutters


No Edge Cases


<article class="grid_6">Article</article>

Meanwhile, in 2008

CSS Systems by Natalie Downe

Consistent Systems

Custom Grids

Frameworks Lock You In

fine until you try something new…

Static, fluid, elastic, or a combo?

equal columns, or asymmetrical? how many?

gutters in padding, left, right, or split-margins?

responsive in what ways?

Grid built with percentages

Container defined with ems / max-width: 100%


Container Responds to Viewport and Font-size

contents respond to the container


No Restrictions


No Ugly Classes


Ugly Math & Meaningless Numbers…

.grid-span {
  width: percentage(((3*4em) + (2*1em)) / ((12*4em) + (11*1em))); // 23.7288136%
  margin-right: percentage(1em / ((12*4em) + (11*1em))); // 01.6949153%
  padding-left: percentage(((1*4em) + (1*1em)) / ((12*4em) + (11*1em))); // 08.4745763%



patterns add meaning

.grid-span {
  width: span(3);
  margin-right: gutter();
  padding-left: span(1 wide);

Responsive Web Design

fluid layouts, with fluid images, and media queries

Mobile First

design for the smallest screens, then build up

/* small screen layout */

@media ( min-width: 35em ) { /* larger layout… */ }


Any Grid System, On Demand

just pass in different settings…

$blueprint: (
  'columns': susy-repeat(12, 30px),
  'gutters': 10px,
  'spread': 'narrow',
  'container-spread': 'narrow',
$960: (
  'columns': susy-repeat(12, 60px),
  'gutters': 20px,
  'spread': 'narrow',
  'container-spread': 'wide',


Grid Systems Are Overkill

(yeah, I know, you use Bootstrap)

“Tiny Bootstraps For Every Client

Chapter 6: DIY Grids

with any layout technique…

Fluid Grids Require Math

make the math simpler…

target / context == multiplier

width: percentage(target / context)

Margin Gutters Ruin The Math

get rid of them!

.grid-span {
  width: percentage(((3*4em) + (2*1em)) / ((12*4em) + (11*1em))); // 23.7288136%
  margin-right: percentage(1em / ((12*4em) + (11*1em))); // 01.6949153%
  padding-left: percentage(((1*4em) + (1*1em)) / ((12*4em) + (11*1em))); // 08.4745763%

Span 3 of 12 [Without Gutters]

.element {
  // float, or flexbox, or css-table…
  width: percentage(3/12);
.element {
  // float, or flexbox, or css-table…
  width: calc(3 / 12 * 100%);

Like CSS Systems for OOCSS

simple math, open system


No Ugly Classes

(unless you really want them)


Works With Any Technique

float, flex, display-table, etc…


Implicit Relationships > Explicit Grids

let the browser figure it out…

Chapter 7: Paradigm Shift

CSS is becoming more extensable

Custom Properties (aka Variables)

they inherit!

--property-name: any value;

var( --property-name , fallback)

custom property support

calc( var( --span ) / var( --columns ) * 100% )

calc support

Calc + Custom Properties == Grids!

media-queries can change settings

:root {
  --columns: 3;
  --gutters: 0.5em;

  @media (min-width: 50em) {
    --columns: 6;
    --gutters: 1em;
* {
  --width: calc(var(--span) / var(--columns) * 100%);
  width: var(--width, initial);

.calc-gutters .item {
  --span: 1;
  float: left;
  padding: var(--gutters);

Viewport Units

vw, vh, vmin, vmax

viewport unit support


height: 100vh

(remember to set overflow)


min-height: 100vh

Full-Width, Breaking The Container…

calc( 50% - 50vw )

.full-width {
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);

breaking the container

Chapter 9: CSS Grid

omg, why did we talk about anything else?

brain expanding meme: frameworks, diy grids, flexbox, display grid

Actual, Real, Layout In The Browser

this is not a rickroll

Caniuse Grids

Nothing like it, at all

anything else is a lie…

The Spec is Complex

Getting Started Is Not

Defining Columns & Rows

.container {
  display: grid;
  grid-template-columns: 300px 1fr minmax(30em, 50%) 10vw; /* mixed units! */
  grid-template-rows: 300px 300px 300px; /* repeat(3, 300px) */
  grid-gap: 10px;

(similar to defining columns/gutters in any grid system)

% defines a fraction of total space

vw defines a fraction of the viewport

fr defines a fraction of remaining space

1fr == minmax(auto, 1fr)

use minmax(0, 1fr) to allow shrinking

Lines 1-indexed

Grid Lines

Also: Negative 1-indexed

Grid Lines (negative)

Column/Row Gaps

Grid gap

Grid-Items: By Line

.red {
  grid-column: 1 / 4;
  grid-row: 2 / span 2;
.green {
  grid-column: 2 / -1;
  grid-row: 1 / -2;

Placing grid items

Grid area desire

Named Grid-Areas

body {
  display: grid;
  grid-template-areas: 'header header'
                       'nav    main'
                       'footer footer';
  grid-template-columns: minmax(10em, 20%) 1fr;
  grid-template-rows: auto 1fr auto;

h1 { grid-area: header; }
nav { grid-area: nav; }
main { grid-area: main; }
footer { grid-area: footer; }

Grid area results labeled

You Can Do All Kindsa’ Cool Shit

Autofill, Named Lines, Implicit Grids…


usable templates, with fallbacks already written…

Rachel Andrew and Jen Simmons


Two Dimensions!

columns & rows


Flexible Markup Order!


Nesting Still Matters

We need subgrid and display: contents


Data-Driven Layouts

<div style=" --start: 30; --duration: 60;">

Schedule grid

Click it all together
Put your helmet on


Use @supports For Fallbacks

fallback to float, or flexbox, or display-table…

@supports (display: grid) { 
  /* grid layout… */ 

@supports not (--custom: property) { 
  /* variable fallbacks… */ 

Susy3 Is a Fallback Plan

now using a grid-like functional syntax

Chapter 10: Do It

Start With Grid

it’s the only real layout option…

Fix the Box Model

Stay In The Flow

Think Dynamically

how do objects relate and change?

Remove External Gutter Math

Get Creative!

the world is ready for more than 12-columns…

Epilogue: Going Too Far

Susy CSS (for fun)

more power/complexity than you need on any one project…

See the Pen SusyCSS by Miriam Suzanne (@mirisuzanne) on CodePen.