Don’t Use My Grid System The Past & Future of Web Layout
Don’t Use My Grid System The Past & Future of Web Layout
Boulder Python — February 12, 2019
OddBird
Full-Service Consulting (with Python)
Sass
Susy
No Susy
The End!
Damn, that was easy…
Some History…
How did we get here?
1993: HTML
Markup Language
OddBird siblings (Jonny, Carl, and Miriam) in 1994
1997: <table>
HTML 3.2
(╯'□')╯︵
┻━┻
“TABLES ARE FOR DATA”
👎
Limited Styling
👎
Strict (non-linear) Markup
👎
Accessibility Nightmare
“Code is Communication”
—Sarah Drasner *
* (once)
Table Layouts Destroy Meaning
for both humans and machines…
1996 2000: Cascading Style Sheets
Principle of Least Power
(This is a Feature)
“Resilient, Declarative, Contextual”
Writing CSS is effectively setting up a system of constraints.
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?
A zillion different devices of all sizes (original)
! 👨
Masculine emojis
Feminine emojis
Various people emojis
Go with the flow!
So… Position?
Relative positions have no effect on flow
Absolute positions remove from flow
Absolute/Fixed ->
Overlays Only
off-canvas, drop-downs, tooltips, modals, etc…
Floats?
float:
left
// float:
right
Great for elements that should… float…
Requires ClearFix (Hack)
apply to any container element…
// "Micro" Clearfix Mixin
@mixin clearfix {
&::after {
clear: both;
content: ' ';
display: table;
}
}
// "Micro" Clearfix Class
.clearfix::after { /* same… */ }
display:
flow-root
the new clearfix alternative, with very little support…
👍
Flexible Markup & Nesting!
👎
Explicit Widths
floats aren’t very smart about context…
¯\_(ツ)_/¯
not the worst hacks…
Display: Table?
No Margins, Use border-padding
2007-2010: Major Grid Frameworks
Blueprint, OOCSS, 960gs, Susy, etc…
12 column grid, single axis
Span some of those columns!
Add a gutter on the right margin…
Remove the last margin in a row…
Classes Are The API
class="
column col6of12 last
"
960gs uses “split” gutters to avoid last
…
👍
Provide Consistent Patterns
and take care of all the hacks…
👍
Developers Can Ignore CSS
👎
Developers Will Ignore CSS
👎
One Size Fits No One
CSS Systems by Natalie Downe
- Systems > Frameworks
- Fluid Grids
- Static (
px
) | Elastic (em
) Containers
👍
“Responsive” before Responsive™
Fluid Grid Math Sux
.grid-span {
width: 23.7288136%;
margin-right: 01.6949153%;
padding-left: 08.4745763%;
}
target / context == multiplier
width: percentage(target / context)
Fluid Grid Math Sux
.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%
}
Sass (2006) & Susy (2009)
.grid-span {
width: span(3);
margin-right: gutter();
padding-left: span(1 wide);
}
👍
Any Grid System, On Demand
👎
Usually Overkill
No Susy
DIY Grids…
1. Fix the Box Model
(IE got it right the first time)
Content-Box: 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;
}
2. Remove Gutters from Grid Math
Use padding
rather than margin
OOCSS uses fractions to keep math simple…
Fractions > Columns
percentage(
target / context
)
A no-framework Sass grid
3. Use the “New” Toys…
2011: calc()
Firefox 4
Mixed-Unit Calculations
calc(
16px
+
20%
)
2012: Flexbox
Chrome 21
Global Flow
flex-direction: column;
| flex-wrap: wrap;
Individual Sizing
grow, shrink, basis =>
flex: 1 2 auto
;
👍
-Grow
& -Shrink
Define Relationships!
👎
Nesting Matters
👎
Poor Page-Level Performance
2014: --css-
variables
Firefox 31 (unless you count currentColor
)
.example {
--color: red;
background: var(--red);
}
-<empty>-
browser-prefix
--aka
:
'custom properties'
;
var(
--property-name
, fallback)
Sass Variables Scope
Based on Source File Structure
:root { $columns: 2; }
.nested-class { /* $columns == undefined */ }
@media (min-width: 30em) {
:root { /* $columns == undefined */ }
.nested-class { /* $columns == undefined */ }
}
CSS Variables Inherit
Based on DOM & Cascade
:root { --columns: 2; }
.nested-class { /* var(--columns) == 2 */ }
@media (min-width: 30em) {
:root { --columns: 6; }
.nested-class { /* var(--columns) == 6 */ }
}
Inherit Everywhere:
:root {
--brand-color: hsl(330, 100%, 45%);
}
Don’t Inherit:
* {
--brand-color: initial;
}
Safe Inline Styles
<button style="--color: blue;">
Use the Variable…
button {
background: var(--color, red);
}
…or Ignore the Variable
button.green {
background: green;
}
Avoid Nesting…
button {
background: blue
}
.this button {
background: red;
}
…For Lower Specificity
button {
background: var(--btn-color, blue);
}
.this {
--btn-color: red;
}
Combine with calc()
* {
--width: calc(var(--span) / var(--columns) * 100%);
box-sizing: border-box;
width: var(--width, initial);
}
.calc-gutters .item {
--span: 1;
float: left;
padding: var(--gutters);
}
Media Queries…
:root {
--columns: 3;
--gutters: 0.5em;
@media (min-width: 50em) {
--columns: 6;
--gutters: 1em;
}
}
CSSSusy!
:root {
--susy-columns: 1;
--susy-gutters: 0.25;
--susy-spread: -1;
--susy-container-spread: -1;
/* --susy-static-grid: 1; */
/* --susy-debug-color: green; */
}
A Variable for Every Function…
* {
/* gutter output math */
--su-inside-gutters: calc(
var(--gutter-width) * var(--gutters-inside)
);
--su-gutters-left: calc(
var(--gutter-width) * var(--gutters-left)
);
}
AG Grid Nesting Test from OOCSS [permalink / source]
Susy, scribbled out
Viewport Units
vw
, vh
, vmin
, vmax
Full Height…
height:
100vh
Sticky-Footer…
min-height:
100vh
Breaking Out of the Container…
calc(
50% - 50vw
)
2017: CSS Grid
Firefox 52 & Chrome 57 & Safari 10
Nothing Like It
At All
The Spec is Complex…
Getting Started Is Not
Truly Two-Dimensional Layouts
columns & rows! mixed units!
.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;
}
Grid-Items: By Line
.one {
grid-column: 1 / 4;
grid-row: 2 / span 2;
}
.two {
grid-column: 2 / -1;
grid-row: 1 / -2;
}
Global Flow && Sizing
With auto
escape-hatch to element flow…
body {
display: grid;
grid-gap: 0.5em;
grid-template-rows: auto 1fr auto;
grid-template-columns: minmax(14em, auto) minmax(0, 1fr);
}
Named Areas
body {
grid-template-areas: 'header header'
'nav main'
'footer footer';
}
h1 { grid-area: header; }
nav { grid-area: nav; }
main { grid-area: main; }
footer { grid-area: footer; }
Single Source of Truth
@media (max-width: 50em) {
body {
grid-template: 'header'
'nav'
'main'
'footer';
}
}
%
=> relative to parent width
vw
=> relative to the viewport
fr
=> relative to available space
1fr
==
minmax(auto, 1fr)
use minmax(0, 1fr)
to allow shrinking
2018: Intrinsic Web Design
Fluid & Fixed
Stages of Squishiness
- fixed
- fluid (
fr
) - fluid-until-fixed (
minmax()
|flex-basis
) - flow (
auto
)
Nested Contexts
flexbox, grid, float, etc…
Expand & Contract Content
justify, wrap, flex, etc…
Media Queries, As Needed
repeat(
auto-fit
, minmax(
20em
,
1fr
))
Data-Driven Layouts
<div style="
--start
: 30;
--duration
: 60;">
Screenshot of schedule grid
Bar Charts
<dl class="chart" style="--scale: 100">
<dt class="date">2000</dt>
<dd class="bar" style="--value: 45">45%</dd>
<dt class="date">2001</dt>
<dd class="bar" style="--value: 100">100%</dd>
<!-- etc… -->
</dl>
```html
.bar {
--start: calc(var(--scale) + 1 - var(--value));
grid-row-start: var(--start);
}
2000 | |
---|---|
2001 | |
2002 | |
2003 | |
2004 | |
2005 | |
2006 | |
2007 | |
2008 | |
2009 |
index | value |
---|---|
0 | 53 |
1 | 10 |
2 | 21 |
3 | 2 |
4 | 44 |
5 | 31 |
6 | 12 |
7 | 6 |
8 | 37 |
9 | 22 |
10 | 41 |
11 | 37 |
12 | 8 |
13 | 73 |
14 | 15 |
name | x value | y value | size == z value |
---|---|---|---|
item-0 | 44 | 66 | 8 |
item-1 | 93 | 85 | 17 |
item-2 | 38 | 88 | 1 |
item-3 | 21 | 62 | 15 |
item-4 | 10 | 64 | 24 |
item-5 | 30 | 4 | 14 |
item-6 | 36 | 55 | 22 |
item-7 | 86 | 74 | 19 |
item-8 | 35 | 91 | 7 |
item-9 | 69 | 23 | 5 |
item-10 | 99 | 88 | 9 |
item-11 | 71 | 34 | 13 |
item-12 | 66 | 83 | 22 |
item-13 | 91 | 48 | 7 |
item-14 | 26 | 69 | 20 |
item-15 | 97 | 70 | 19 |
item-16 | 40 | 19 | 24 |
item-17 | 96 | 96 | 1 |
item-18 | 52 | 57 | 5 |
item-19 | 89 | 61 | 12 |
Levitated Toy Factory at Beyond Tellerand
Rachel Andrew: gridbyexample.com
examples, templates, and fallbacks
Jen Simmons: youtube.com/layoutland
also: labs.jensimmons.com
Inspired by Stacy Kvernmo [permalink / source]