I Don’t Do Django
but I love the template language…
Prologue: Establishing Cred
Small Team, Outside Consulting
User Experience Design
HTML/CSS Implementation
(and open-source design-system tools)
// 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%),
);
¯\_(ツ)_/¯
Another F*cking Grid System
Flashback: The History of Web Layout…
Chapter 1: Ugh, Tables
(Lilly Ryan)
Silly Dev,
Tables Are For Data
👎
Limited Styling
👎
Strict (non-linear) Markup
👎
Accessibility Nightmare
Also An SEO/Legal Problem
(Lindsey Dragun)
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
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…
that’s, like, a small fraction of your audience?
!👨
Not Just WCAG Accessibility
(but also that)
❤
EMPATHY
for all kinds of not you
That’s The Job
Your Team, Please:
<
/
rant>
Chapter 3: Layout Concepts
Fix the Box Model
(IE got it right the first time)
Content-Box [Default]
total = width/height
+
borders
+
padding
Border-Box
total = width/height
👍
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
See the Pen Flow! by Miriam Suzanne (@mirisuzanne) on CodePen.
See the Pen !Flow by Miriam Suzanne (@mirisuzanne) on CodePen.
See the Pen Flow with Legos by Miriam Suzanne (@mirisuzanne) on CodePen.
Chapter 4: Layout Techniques
[pre 2017]
👎
Relative Positioning…
no effect on the flow, similar to transform: translate()
👎
Absolute (or Fixed) Positioning…
removed from the flow entirely…
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…)
Kinda Flows…
See the Pen Flow: Kinda by Miriam Suzanne (@mirisuzanne) on CodePen.
This Makes Sense For Text-Wrap
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;
}
See the Pen Flow: Kinda (Clearfix) by Miriam Suzanne (@mirisuzanne) on CodePen.
display:
flow-root
the new clearfix alternative…
Overflow:
Hidden
(Hack) for fluid columns, and clearing containers…
(be careful)
See the Pen Overflow: Hidden (Hack) by Miriam Suzanne (@mirisuzanne) on CodePen.
👍
Flexible Markup & Nesting!
<section>
<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>
<div>
<div class="next">Next! (overflow hack)</div>
<div> <!-- They all collapse! -->
<div>
<div>
<div>
<div>
<div>
<div>
<div class="last">Last! (floating)</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
👎
Always Define The Width
floats aren’t very smart about context…
¯\_(ツ)_/¯
Sub-Pixel Rounding?
Modern Browsers
sub-pixel browser rendering vs. float isolation
See the Pen Don't bother with "isolation" in modern browsers by Miriam Suzanne (@mirisuzanne) on CodePen.
See Responsive Design’s Dirty Little Secret by John Albin Wilkins
Backgrounds Still Round Badly
(even if you try isolating them)
See the Pen SubPixel Rounding by Miriam Suzanne (@mirisuzanne) on CodePen.
👎
Inline-Block…
invasive and confusing hacks required
¯\_(ツ)_/¯
Display: Table?
no margins, use border-padding
One Row at a Time…
See the Pen Display Table by Miriam Suzanne (@mirisuzanne) on CodePen.
(flexbox does this better…)👍
Flexbox
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
)
Full-Height Equal Columns
relationships flex & flow!
See the Pen Full-height Flexbox by Miriam Suzanne (@mirisuzanne) on CodePen.
👎
Still A One-Dimensional Flow
(with line-wrapping options)
👎
Nesting Matters Too Much
We need display: contents
👍
Super great for inline layouts
See the Pen Flexbox for Media Object by Miriam Suzanne (@mirisuzanne) on CodePen.
👎
Poor Performance for Page Layouts
Chapter 5: Grid Systems, A Historic Detour
mostly using floats…
12 Equal Columns
👍
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. */
.column,
.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
Spanning Columns
Remove The Last Gutter
(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
See the Pen It depends by Rachel Smith (@rachsmith) on CodePen.
by Rachel Smith
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;}
.unit{float:left;zoom:1;}
.size1on1{float:none;}
.size1on1{float:none;}
.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…
<article class="
unit size1on2
">Article</article>
2010: 960 Grids
gutters split left and right…
.container_12,
.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…
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%
}
Susy
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)
calc(
var(
--span
) / var(
--columns
) * 100%
)
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);
}
See the Pen Padding or Calc() by Miriam Suzanne (@mirisuzanne) on CodePen.
Viewport Units
vw
, vh
, vmin
, vmax
Full-Height…
height:
100vh
(remember to set overflow
)
See the Pen Full-height CSS Grid by Miriam Suzanne (@mirisuzanne) on CodePen.
Sticky-Footer…
min-height:
100vh
See the Pen Sticky-Footer with CSS Grid by Miriam Suzanne (@mirisuzanne) on CodePen.
Full-Width, Breaking The Container…
calc(
50% - 50vw
)
.full-width {
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
}
https://css-tricks.com/fun-viewport-units/
intrinsic ratios, responsive font-sizing, and more…
Chapter 9: CSS Grid
omg, why did we talk about anything else?

Actual, Real, Layout In The Browser
this is not a rickroll
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
Also: Negative 1-indexed
Column/Row Gaps
Grid-Items: By Line
.red {
grid-column: 1 / 4;
grid-row: 2 / span 2;
}
.green {
grid-column: 2 / -1;
grid-row: 1 / -2;
}
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; }
You Can Do All Kindsa’ Cool Shit
Autofill, Named Lines, Implicit Grids…
👍
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;">
See the Pen Bar chart in CSS grid + variables by Miriam Suzanne (@mirisuzanne) on CodePen.
https://css-tricks.com/css-charts-grid-custom-properties/


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.
See the Pen SusyCSS Demo by Miriam Suzanne (@mirisuzanne) on CodePen.