Tweaking your ch-based grid after swapping fonts

Sometime after was released I I stumbled upon Achieving simple design with simple CSS where Alexandre Ruban had picked some of the How Hey Works page apart.

The Fonts, They Are A-Ch-angin’

Permalink to “The Fonts, They Are A-Ch-angin’”

Hey’s CSS unit choice is part of an approach where flow-spacing (micro) and grid-spacing (macro) are derived from the sizing for the text. So let’s start there, with how the text gets sized.

:root {
--type-base: calc(1.6em + 0.5vw);

@media (min-width: 45em) {
:root {
--type-base: calc(0.9em + 0.9vw);

@media (min-width: 91em) {
:root {
--type-base: 2.2em;

html {
font-size: 10px;

body {
font-size: var(--type-base);

Custom properties on :root (html) define the spacing in ems and different type sizes in percentages. As you can see below, the font itself is sized in relationship to the viewport. It is all connected resulting in a cleverly fluid, responsive layout.

All grids are equal. But some grids are more equal than others.

Permalink to “All grids are equal. But some grids are more equal than others.”

I used these underpinnings for my own site to explore them further. I soon ran into an issue were the center 3 columns moved outside of the viewport when resizing between the 45em and 91em breakpoints. Let’s see what’s happening there with the grid.

@media (min-width: 45em) {
.grid {
[max] 1fr
[l] minmax(11ch, 0.7fr)
[m] repeat(3, [m] 21.66ch)
[m] minmax(11ch, 0.7fr)
[l] 1fr

Remember how the font-size affects everything? Well, internal font proportions play a role in that too. The middle three columns delineated by the [m] grid lines are sized with the ch unit. You might have heard to them being referred to as character (width) units, but the definition is a little more esoteric—one ch is…

The advance measure of the glyph “0” of the element’s font.

It’s the width of 0 (zero). Glad to have you back.

I’m using the Inter Var typeface, so I need to find out what’s going on with its 0.

In order to do that I edited the page in the devtools and inserted the following snippet into the DOM.

<!-- A red square so I have something to look at-->
<div id="emMeasure" style="width:1em; height: 1em; background-color:red;"></div>

<!-- Call getOneEmInPx() from browser console-->
function getOneEmInPx() {
const emDiv = document.querySelector('#emMeasure');
const width = emDiv.getBoundingClientRect().width;
console.log({ width });

Then I called getOneEmInPx() from the browser console.

For Inter Var, I got a value of 10. On Hey’s website, it returned 7.953125.

So when I multiplied the two ch values from the previous .grid definition

11ch × 0.7953125 = 8.7484375ch ≈ 8.75ch
21.66ch × 0.7953125 = 17.22646875ch ≈ 17.23ch

As soon as I plugged these values into the grid (and did the same for the 91em breakpoint) the grid behaved in the exact same way as the one one