Entry 06
One fluid scale for type and space
Use it when a design has more than two or three font sizes. Six numbers describe every size, and the browser derives the steps. It replaces a table of sizes per breakpoint, and it replaces a generator that someone has to find and run again.
Code
:root {
--narrow: 20;
--wide: 77.5;
--size-narrow: 1.125;
--size-wide: 1.25;
--ratio-narrow: 1.2;
--ratio-wide: 1.25;
--fluid: clamp(0rem, (100vw - var(--narrow) * 1rem) / (var(--wide) - var(--narrow)), 1rem);
--at-narrow: calc(var(--size-narrow) * (1rem - var(--fluid)));
--at-wide: calc(var(--size-wide) * var(--fluid));
--step--1: calc(var(--step-0) / var(--ratio-narrow));
--step-0: calc(var(--at-narrow) + var(--at-wide));
--step-1: calc(var(--at-narrow) * var(--ratio-narrow) + var(--at-wide) * var(--ratio-wide));
--step-2: calc(var(--at-narrow) * pow(var(--ratio-narrow), 2) + var(--at-wide) * pow(var(--ratio-wide), 2));
--step-3: calc(var(--at-narrow) * pow(var(--ratio-narrow), 3) + var(--at-wide) * pow(var(--ratio-wide), 3));
--step-4: calc(var(--at-narrow) * pow(var(--ratio-narrow), 4) + var(--at-wide) * pow(var(--ratio-wide), 4));
--space-s: var(--step-0);
--space-m: calc(1.5 * var(--step-0));
--space-l: calc(2 * var(--step-0));
--space-s-l: calc(var(--at-narrow) + 2 * var(--at-wide));
}
body { font-size: var(--step-0); }
h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-2); }
small { font-size: var(--step--1); }
.card {
display: grid;
gap: var(--space-s);
padding: var(--space-s-l);
}Why it works, the rules and the credits
Why it works
- The first six lines are the whole design decision. Widths and sizes are in rem, written as plain numbers, so 20 is 320px and 1.125 is 18px. Body text runs from 18px on a 320px screen to 20px on a 1240px one, and each heading step is 1.2 times the last on the phone and 1.25 times on the desktop.
--fluidis a length that is 0 at the narrow width, 1rem at the wide width and a straight line between. It holds the onlyclamp(), and that one bounds every token.--at-narrowand--at-wideare the two base sizes, each weighted by how close the viewport is to its width. Their sum is step 0.pow()raises each ratio to the step number. A step is the narrow scale's size times one weight plus the wide scale's size times the other, which is the line Fluid sizes withclamp()draws between two points.- A space token is a multiple of step 0, so it grows as much as body text does. A pair such as
--space-s-lgives the two terms different multipliers. It is the small size on the phone and the large size on the desktop, 18px to 40px here.
Rules
- Write the inputs as plain numbers. With
20remand77.5remthe--fluidline divides a length by a length, and Firefox does not support that. - Change an input in the rule that declares the steps. A step takes its value where it is declared, so a ratio set on a descendant changes nothing below it.
- Derive sizes below step 0 from step 0 and the narrow ratio, as
--step--1does. With both ratios a small size shrinks as the screen grows. - Check the top step against the limit in Fluid sizes with
clamp(). Stepnpasses when(size-wide / size-narrow) × (ratio-wide / ratio-narrow)ⁿis 2.5 or less. The example gives 1.31 at step 4. - Write a pair only where a layout uses it, and never use one for a font size. A pair is steep on purpose and breaks that limit.
- For a scale that follows the container, write
100cqiin place of100vw. Container queries with container units has the rules. - Components use the tokens and never repeat the math.
Support
- Chrome
- 120
- Firefox
- 118
- Safari
- 15.4
Set by pow(). Tested in Chrome 150 and real Safari 27 on 2026-10-01, where every step came out within 0.001px of the formula.
Credits
Borrowed from: James Gilyead, Designing with fluid type scales, 2020-02-01, for the two scales · Trys Mudford, CSS-only fluid modular type scales, 2020-02-02, and Fluid custom properties, 2020-02-03 · James Gilyead, Designing with a fluid space palette, 2021-03-16, for space pairs. Utopia prints one finished clamp() per step from a calculator, because CSS had no powers in 2020. With pow() the browser does that math.
Background: Miriam Suzanne, Responsive and Fluid Typography with Baseline CSS Features, 2025-12-16
Docs: MDN: pow() · Utopia type calculator