Remember Tables?

back when I was a kid…

Young OddBirds


flipping tables

It’s a hack!



Limited Styling + Strict Markup


Accessibility Nightmare

Source order and semantics both broken…

Hey look, CSS!

separate presentation from markup

CSS is Awesome

this is a feature!

CSS Describes Relationships

setting explicit height & width is dangerous…

Design Flexible Systems!

how is this going to change…?

…when the content changes?

…when the viewport changes?

…when the context changes?

So many screens

Whenever You Can…

Go With The Flow

CSS Layout Options!

but first…

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 👎

html {
  box-sizing: border-box;

* {
  box-sizing: inherit;


Relative Positioning?

doesn’t affect layout at all…

Position Relative

relative to current position / similar to translate

Does Anyone Use Relative Positions?

For anything other than setting a context…


Absolute (or Fixed) Positioning?

No actual structure…

Position Absolute

based on positioned ancestor (or viewport)…

Great For Overlays… Only.

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

CSS Floats!

Not the worst hack

Floated images in text

Kinda Flows

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 containers


Nesting Freedom!


Sub-Pixel Rounding

not so bad anymore…

Solves (Outdated) Sub-Pixel Rounding

removes horizontal flow, adds bloat, takes all your margins

.isolate {
  float: left;
  margin-right: -100%; // remove horizontal flow…
  margin-left: 25%; // position everything off the left edge…

Float Isolation Is Overkill

but an interesting trick…

Grid Systems?

Mostly using floats

2007: Blueprint CSS

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;}

<article class="column col6of12 last">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;

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

CSS Systems

Consistent Systems

Custom Grids

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%

target / context == multiplier

width: percentage(target / context)


Super Flexible!

responds to font-size and viewport, with easy iterations…


Shitty math…

.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);

You (Probably) Don’t Need Grid Systems

only as a last-resort…

Kill the Margin Gutters

they ruin the math…

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%);

Calc + Variables!

: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);

Do As Little As Possible

100% width is a default, etc…


too many hacks required… 👎


Display: Table?

use border-padding for internal margins


Kinda like floats, kinda like table, better than both


So Many Options

.container {
  align-items: stretch; /* equal-height! */
  display: flex;
  justify-content: space-between;
.container {
  align-items: center; /* vertical-centering! */
  display: flex;
  flex-direction: row-reverse;


height: 100vh

(remember to set overflow)


min-height: 100vh

Breaking Out (side note)…

calc( 50% - 50vw )

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


Flexing is Magic

define relationships, not explicit results


Only One-Dimensional Flow

(with line-wrapping options)


Nesting Matters Too Much

We need display: contents

CSS Grid!


Caniuse Grids

Nothing like it, at all

anything else is a lie…

The Spec is Complex

but getting started can be simple

You don't have to read the whole spec

Grid-Lines: Container

.container {
  display: grid;
  grid-template-columns: 300px 300px 300px 300px;
  grid-template-rows: 300px 300px 300px;
  grid-gap: 10px;
.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(3, 1fr);
  grid-gap: 10px;

Mix Any Units!

.container {
  display: grid;
  grid-template-columns: 300px repeat(4, 1fr) 10em;
  grid-gap: 10px;

Lines 1-indexed

Grid Lines

Lines 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;

% 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

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

Atomic Legos
Put your helmet on

Atomic Legos

Name grid lines

You Can Autofill & All Kindsa’ Cool Shit


Two Dimensions!


Flexible Markup Order!


Nesting Still Matters

We need subgrid and display: contents

Use @supports For Fallbacks

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

(Susy3 is here to help, using grid-like syntax)

Schedule grid

usable templates, with fallbacks already written…

Rachel Andrew and Jen Simmons

Start With Grid

it’s the only real layout option…

Fix the Box Model

Use The Flow

Remove External Gutter Math

Get Creative!

the world is ready for more than 12-columns…

Susy CSS (for fun)

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

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