Thirty years of front end
From tables to tokens
Every era fixed the last one's problem and left its own furniture behind. Most products still carry all of it.
One line through thirty years: how pages were laid out, how they were scripted, and the idea of programming under both. Move it from moment to moment; each shows a few lines of what was written then. The timeline is TokenKit's own Timeline component, telling the story of how it led to building things like it.
- Tables
Layout was a table, spacing was a GIF, and every page was drawn for one window.
HTML <table width="800"><tr> <td><img src="spacer.gif" width="20"></td> <td><font face="Arial">Welcome!</font></td> </tr></table> - Flash
ActionScript 1: handlers on buttons, prototypes underneath. Scripting, not yet objects.
ActionScript 1 on (release) { gotoAndPlay("intro"); } - The Zen Garden
One HTML file, restyled by CSS alone. Content and presentation, separated.
CSS #pageHeader h1 { background: url(h1.gif) no-repeat; text-indent: -9999px; } - jQuery
One road: the open web scripts the DOM, at scale.
jQuery $("#menu li").hover(function () { $(this).addClass("over"); }); - ActionScript 3
The other road: Flash goes all in on classes. Truly object-oriented.
ActionScript 3 public class Hero extends MovieClip { public function Hero() { stop(); } } - Responsive web design
Ethan Marcotte names it: fluid grids, flexible images, media queries. Breakpoints should follow the design.
- Device sizes
The industry turns it into phone, tablet, desktop, and selectors built to win.
SCSS @media (max-width: 768px) { .nav > li > a:hover { color: $brand !important; } } - React
The interface becomes a function of state. Declarative, at last.
React render() { return <Button onClick={this.save}>Save</Button>; } - Container queries
A component answers the box it is given. What responsive design always wanted.
CSS @container (inline-size > 30rem) { :where([data-tk="card-body"]) { columns: 2; } } - Values and states
Values free of any one tool. States declared, not toggled.
A state machine const save = { idle: { SUBMIT: "busy" }, busy: { DONE: "saved", FAIL: "error" }, };
- Scripting to
- Object-oriented to
- Declarative to
- State machines to
Tables, 1996
The film
Credits and sources
- Dave Shea, CSS Zen Garden, 2003.
- Ethan Marcotte, Responsive Web Design, A List Apart, May 2010. In 2012 Marcotte argued that breakpoints should follow the design, not devices (.net magazine, quoted in Jeremy Keith, Fanfare for the common breakpoint); in 2017 he asked why a component cannot be styled by the space it has rather than the viewport (“On container queries”, linked from adactio.com). Container queries shipped in every engine in 2023.
- The code is illustrative: a few lines in the style of each era, not taken from any one site.