Web typography is broken. Here’s how we can fix it

Questing for the holy grail of web typography: a baseline, cap height, and more in CSS.

Typesetting on the web

Why grids, why?

Josef Müller-Brockmann casually designing a few website wireframes… in 1961.

A typographic specification

Best practises

Handling spacing

Learn from the past

$base-font-size: 16px; // this is the grid leading
@include establish-baseline; // initialise the grid
h1 {
@include adjust-font-size-to(20px, 2); // 20px font-size with line-height at 2 units of baseline
@include leader(1); // one line of space above
@include trailer(2); // one line of space below
}

Computing cap height

// variables.scss
// Add typefaces here.
// Add weight and style details too.
// Set cap height to set to the baseline.
$bodytype: (
font-family: 'Georgia, serif',
regular: 400,
bold: 700,
italic: italic,
cap-height: 0.66
) !default;
$headingtype: (
font-family: 'Helvetica, sans-serif',
regular: 400,
bold: 700,
cap-height: 0.66
) !default;
// Here are some local fonts cap-height sizes to get you started:
// Georgia: 0.66, Times / Times New Roman: 0.65, Palatino: 0.52
// Lucida Grande: 0.72, Helvetica: 0.66, Verdana: 0.76, Tahoma: 0.76
cap-height * computed line-height
p {
@include sassline($fontsize, $font, $lineheight: 2, $below: 2, $breakpoint: 0);
}
$current-breakpoint: 0 !default;
@mixin min-width($breakpoint) {
$current-breakpoint: $breakpoint;
@media screen and (min-width: get-breakpoint-width($breakpoint)) {
@content;
}
$current-breakpoint: 0;
}

First steps

p {
@include type($font: $display-type, $fontsize: 1rem, $lineheight: 2, $leader: 0, $trailer: 1);
@include breakpoint(break-1) {
@include type($display-type, $fontsize: 1.25rem, $lineheight: 2, $leader: 0, $trailer: 2);
}
}
You took too much

Prototyping MegaType

npm install megatype --save-dev
bower install megatype --save-dev
@import megatype;
// config.scss// enable responsive baseline & type scaling.
// increases root font size from each breakpoint, starting from the min size specified in the rootsizes below
$baseline-scaling: false !default;
// enable formal baseline grid
// snaps all type to the baseline grid
$baseline-snap: true !default;
// map for flexible retrieval of breakpoint info
$breakpoint-map: (
0: (
start: 0px,
max: 420px,
rootsize: 12px
),
1: (
start: 480px,
max: 560px,
rootsize: 14px
),
2: (
start: 768px,
max: 840px,
rootsize: 16px
),
3: (
start: 980px,
max: 1080px,
rootsize: 18px
),
4: (
start: 1280px,
max: 1440px,
rootsize: 20px
)
) !default;
$sans: (
font-family: '"Helvetica Neue", Arial, sans-serif',
regular: normal,
bold: bold,
cap-height: 0.71
) !default;
$serif: (
font-family: 'Georgia, serif',
regular: normal,
bold: bold,
cap-height: 0.69
) !default;
@include megatype;.container {
@include set-container;
}
p {
// we can set our type using pixels
@include typeset($font: $sans, $fontsize: 16px, $lineheight: 24px, $leader: 0, $trailer: 16px);
@include min-width(1) {
// or we can use rems
@include typeset($sans, 1.25rem, 2rem, 0, 1rem);
}

// we can set several breakpoints at once
@include min-width(2 3) {
// or we can use baseline units
@include typeset($sans, 1, 2, 0, 1);
}
@include min-width(4) {
// or we can use any combination
@include typeset($sans, 16px, 2, 1, 1rem);
}
}
p {
font-size: 1.33333333rem; // 16px = 1.33 * 12px rootsize
line-height: 1.5; // 24px = 1.5 * 16px
top: -0.47333333rem; // shifted up so baseline sits on grid
margin-bottom: 0; // rounds to zero; no margin needed
}
@media (min-width: 30em) {
p {
font-size: 1.25rem; // 1.25rem
line-height: 1.6; // 2rem is 1.6 * 1.25rem
top: -0.44375rem; // shifted up so baseline sits on grid
margin-bottom: 0; // rounds to zero; no margin needed
}
}
@media (min-width: 48em) {
p {
font-size: 1rem; // 1 baseline unit = 1rem
line-height: 2; // 2 baseline units with 1rem font-size = 2
top: -0.355rem; // shifted up so baseline sits on grid
margin-bottom: 0; // rounds to zero; no margin needed
}
}
@media (min-width: 61.25em) {
p {
font-size: 1rem; // 1 baseline unit = 1rem
line-height: 2; // 2 baseline units with 1rem font-size = 2
top: -0.355rem; // shifted up so baseline sits on grid
margin-bottom: 0; // rounds to zero; no margin needed
}
}
@media (min-width: 80em) {
p {
font-size: 0.8rem; // 16px = 0.8 * 20px rootsize
line-height: 2.5; // 2 baseline units (2rem) = 2.5 * 0.8rem font-size
top: 0.716rem; // shifted down so baseline sits on grid
margin-bottom: 1rem; // 1rem below
}
}

Gazing beyond

Acknowledgements

Further reading

Web developer, gamer, troublemaker.

Web developer, gamer, troublemaker.