TIL: Baseline grid with Tailwind CSS
I found this really neat technique to establish a baseline grid on a page. It relies on the cap
unit in CSS, which is quite new but well supported in modern browsers. Thanks to cap
it works consistently with different font sizes and even different font families (e.g. for headings).
For any block of text it calculates a --baseline-shift
(padding above) and --baseline-push
(margin below) to align it to the baseline.
I figured it would work well as a Tailwind custom utility. Since they can accept two arguments - a value and a modifier - we can have something like baseline-2/1
, where
2
is the target line height in grid lines1
is the push
/* Accepts "baseline-V" or "baseline-V/M" */
@utility baseline-* {
/* Calculate shift based on --value(integer) */
--baseline-shift: calc(
calc(calc(--value(integer) * var(--spacing)) - 1cap) / 2
);
/* Default push of 1 if modifier not provided */
--baseline-push: calc(
var(--spacing) - var(--baseline-shift)
);
/* Override with --modifier(integer) if provided */
--baseline-push: calc(
calc(--modifier(integer) * var(--spacing)) - var(--baseline-shift)
);
/* ...and apply */
line-height: calc(--value(integer) * var(--spacing));
padding-top: var(--baseline-shift);
margin-bottom: var(--baseline-push);
}
Note the use of var(--spacing)
. This utility expects that --spacing
will be set to the grid size. On this page I have:
@theme {
--spacing: 0.8rem;
}
Now it’s just a matter of applying it to the text:
@layer base {
p, ul, ol, dl {
@apply baseline-2/1;
}
/*
* Apply to headings appropriately based on
* header sizes and desired spacing
*/
h1, h2, h3 {
@apply baseline-3/1;
}
h4, h5 {
@apply baseline-2/1;
}
h6 {
@apply baseline-2/0;
}
}
A benefit of this utility is that you can keep the “UI” of the website free of the baseline, but it’s there if you need it for any div
s or header
s or anything else.
Feel free to check the source of this website to see how I use this utility.