A web font strategy

The Session has been online in some form since the late 1990s. That’s long before web fonts existed.

To begin with, Times New Roman was the only game in town if you wanted serif type on a website. When Microsoft introduced Georgia it was a godsend. A beautiful typeface designed by Matthew Carter for the screen. I put it right at the start of my font stack for The Session.

Later, web fonts came along. Boy, does that short sentence belie the drama! There were very heated discussions about whether web browsers should provide this ability at all, and what it would mean for type foundries.

Microsoft led the way with their prorietary EOT format. Then everyone agreed on WOFF. Finally we got WOFF2, Electric Boogaloo.

Perhaps more important than that, we got intermediaries. Typekit, Fontdeck, and then the big daddy, Google Fonts.

That’s pretty much the state of play today. Oh yeah, and we’ve got variable fonts now.

I remember Nick Sherman presenting the idea of variable fonts at an Ampersand event years ago. I remember thinking “great idea, but it’ll never happen.” Pure science fiction. I thought the same thing when I first saw a conference presentation about a miraculous image format called Scalable Vector Graphics.

Sometimes I like to stop and take stock of what we take for granted in web browsers now. Web fonts. Variable web fonts. SVG. Flexbox. Grid. Media queries. Container queries. Fluid typography. And I haven’t even mentioned how we were once limited to just 216 colours on the web.

Georgia

Given all the advances in web typography, you might be wondering how my font strategy for The Session changed over the years.

It didn’t.

I mean, sure, I added fluid typography. That was a natural extension of my love for liquid layouts and, later, responsive design. But the font stack itself? That was still Georgia all the way.

Y’see, performance has always been a top priority for The Session. If I was going to replace a system font with a web font that the user had to download, it really needed to be worth it.

Over the years I dabbled with different typefaces but none of them felt quite right to me. And I still think Georgia is a beautiful typeface.

“But your website will look like lots of other websites!” some may cry. That used to be true when all we had was system fonts. But now that web fonts have become the norm, it’s actually pretty unusual to see Georgia in the wild.

Lora

Recently I found a font I liked. Part of why I like it is that it shares a lot of qualities with Georgia. It’s Lora by Olga Karpushina and Alexei Vanyashin.

I started to dabble with it and began seriously contemplating using it on The Session.

It’s a variable font, which is great. But actually, I’m not using that many weights on The Session. I could potentially just use a non-variable variety. It comes in fixed weights of regular, medium, semibold, and bold.

Alas, the regular weight (400) is a bit too light and the medium weight (500) is a bit too heavy. My goldilocks font weight is more like 450.

Okay, so the variable font it is. That also allows me to play around with some subtle variations in weights. As the font size gets bigger for headings, the font weight can reduce ever so slightly. And I can adjust the overall font weight down in dark mode (there’s no grading feature in this font, alas).

Subsetting

Lora supports a lot of alphabets, which is great—quite a few alphabets turn up on The Session occasionally. But this means that the font file size is quite large. 84K.

Subsetting to the rescue!

I created a subset of Lora that has everything except Cyrillic, Greek, and Latin Extended-B. I created another subset that only has Cyrillic, Greek, and Latin Extended-B. Now I’ve got two separate font files that are 48K and 41K in size.

I wrote two @font-face declarations for the two files. They’ve got the same font-family (Lora), the same font-weight (400 700), and the same font-style (normal) but they’ve got different values for unicode-range. That way, browsers know to only use appropriate file when characters on the page actually match the unicode range.

The first file is definitely going to be used. The second one might not even be needed on most pages.

I want to prioritise the loading of that first subsetted font file so it gets referenced in a link element with rel="preload".

The switcheroo

As well as file size, my other concern was how the swapping from Georgia to Lora would be perceived, especially on a slow connection. I wanted to avoid any visible rejiggering of the content.

This is where size-adjust comes in, along with its compadres ascent-override and descent-override.

Rather than adjusting the default size of Lora to match that of Georgia, I want to do it the other way around; adjust the fallback font to match the web font.

Here’s how I’m doing it:

@font-face {
    font-family: 'Fallback for Lora';
    src: local('Georgia');
    size-adjust: 105.77%;
    ascent-override: 95.11%;
    descent-override: 25.9%;
}

And then my font stack is:

font-family: Lora, 'Fallback for Lora', Georgia, serif;

It’s highly unlikely that any device out there has a system font called “Fallback for Lora” so I can be pretty confident that the @font-face adjustment rules will only get applied to browsers that have the right local font, Georgia.

But where did those magic numbers come from for size-adjust, ascent-override, and descent-override?

They came from Katie Hempenius. As well as maintaing a repo of font metrics, she provides the formula needed to calculate all three values. Or you could use this handy tool to eyeball it.

With that, Georgia gets swapped out for Lora with a minimum of layout shift.

First-timers and repeat visitors

Even with the layout shift taken care of, do I want to serve up web fonts to someone on a slow connection?

It depends. Specifically, it depends on whether it’s their first time visiting.

The Session already treats first time visitors differently to repeat visitors. The first time you visit the site, critical CSS is embedded in the head of the HTML page instead of being referenced in an external style sheet. Only once the page has loaded does the full style sheet also get downloaded and cached.

I decided that my @font-face rules pointing to the web fonts are not critical CSS. If it’s your first time visiting, those CSS rules only get downloaded after the page is done loading.

And unless you’re on a fast connection, you won’t see Georgia get swapped out for Lora. That’s because I’ve gone with a font-display value of “optional”.

Most people use “swap”. Some people use “fallback”. You’ve got to be pretty hardcore to use “optional”.

But the next page you go to, or the next time you come to the site, you more than likely will see Lora straight away. That’s because of the service worker I’ve got quietly putting static assets into the Cache API: CSS, JavaScript, and now web fonts.

So even though I’m prioritising snappy performance over visual consistency, it’s a trade-off that only really comes into play for first visits.

Next

I’m pretty happy with the overall strategy. Still, I’m not going to just set it and forget it. I’ll be monitoring the CRUX data for The Session keeping a particular eye on cumulative layout shift.

Before adding web fonts, the cumulative layout shift on The Session was zero. I think I’ve taken all the necessary steps to keep it nice and low, but if I’m wrong I’ll need to revisit my strategy.

Update: Big thanks to Roel Nieskens—of Wakamai Fondue fame—who managed to get the file size of my main subsetted font down even further; bedankt!

Responses

Jason Santa Maria

@adactio Love this approach, and Lora looks great 🙌

Also, I feel like I have so many type related things bookmarked, and I still had never seen some you linked to 😅 Thanks!

Kim Johannesen

@adactio We’ve come so fast and take so many things for granted. I remember using sIFR on several projects — what a game changer that was!

8 Shares

# Shared by Sue on Wednesday, March 11th, 2026 at 2:40pm

# Shared by Jason Santa Maria on Wednesday, March 11th, 2026 at 2:40pm

# Shared by Nilesh Prajapati on Wednesday, March 11th, 2026 at 3:12pm

# Shared by Jean-Pierre Vincent - #webperf & #greenit 🚀♻️🌱 on Wednesday, March 11th, 2026 at 3:13pm

# Shared by Luke Dorny on Wednesday, March 11th, 2026 at 3:15pm

# Shared by Roel Nieskens on Wednesday, March 11th, 2026 at 3:49pm

# Shared by Kevin Marks on Wednesday, March 11th, 2026 at 4:20pm

# Shared by Kevin Powell on Wednesday, March 11th, 2026 at 11:16pm

20 Likes

# Liked by Jason Santa Maria on Wednesday, March 11th, 2026 at 2:40pm

# Liked by Sue on Wednesday, March 11th, 2026 at 2:40pm

# Liked by revolutionary girl erin on Wednesday, March 11th, 2026 at 2:40pm

# Liked by Aaron Crowder on Wednesday, March 11th, 2026 at 2:45pm

# Liked by Nilesh Prajapati on Wednesday, March 11th, 2026 at 3:12pm

# Liked by Ashur Cabrera 🐦‍⬛ on Wednesday, March 11th, 2026 at 3:15pm

# Liked by John Warne on Wednesday, March 11th, 2026 at 3:15pm

# Liked by Simon B. Carstensen on Wednesday, March 11th, 2026 at 3:15pm

# Liked by Tyler Sticka on Wednesday, March 11th, 2026 at 3:15pm

# Liked by ℵancym on Wednesday, March 11th, 2026 at 3:16pm

# Liked by Erik Vorhes on Wednesday, March 11th, 2026 at 3:49pm

# Liked by Trey on Wednesday, March 11th, 2026 at 5:17pm

# Liked by Oblomov on Wednesday, March 11th, 2026 at 7:02pm

# Liked by João Miranda on Wednesday, March 11th, 2026 at 11:16pm

# Liked by Kevin Powell on Wednesday, March 11th, 2026 at 11:16pm

# Liked by Uncle Geoff on Wednesday, March 11th, 2026 at 11:47pm

# Liked by Lukas on Thursday, March 12th, 2026 at 12:13am

# Liked by beep on Thursday, March 12th, 2026 at 2:40am

# Liked by Fatih Altinok on Thursday, March 12th, 2026 at 5:04am

# Liked by Jeremy Felt on Friday, March 20th, 2026 at 11:25pm

Related posts

Workaround

Browsers and bugs.

Progressive disclosure with HTML

The `details` element is like the TL;DR of markup.

Overloading buttons

Can you have too much semantics?

Installing progressive web apps

How I’m letting people know they can install The Session to their home screens.

Audio

The sound of worlds colliding.

Related links

The Long Web by Jeremy Keith – An Event Apart Video on Vimeo

This is a talk I gave at An Event Apart about eighteen months ago, all about irish music, the web, long-term thinking, and yes, you guessed it—progressive enhancement.

Tagged with

Tentacular: Douglas Coupland on Helvetica, clip art and the gangly beast that is the internet

Douglas Coupland on web typography.

When I discuss the internet’s feel and its random rodeo of fonts, I think of the freedom, naivety, laziness, greed, cluelessness and skill I see there — it’s a cyberplace as wondrous as the bubbling cradle of pea-soup goo from which life emerged. The internet has a rawness, a Darwinian evolutionary texture. It’s a place where metrics totally unrelated to print typography dictate the look and feel.

Tagged with

Better Google Web Fonts

A single page showing all the weights available from Google fonts at a glance.

Tagged with

Smaller, Faster Websites - - Bocoup

The transcript of a great talk by Wilto, focusing on responsive images, inlining critical CSS, and webfont loading.

When we present users with a slow website, a loading spinner, laggy webfonts—or tell them outright that they‘re not using a website the right way—we’re breaking the fourth wall. We’ve gone so far as to invent an arbitary line between “webapp” and “website” so we could justify these decisions to ourselves: “well, but, this is a web app. It… it has… JSON. The people that can’t use the thing I built? They don’t get a say.”

We, as an industry, have nearly decided that we’re doing a great job as long as we don’t count the cases where we’re doing a terrible job.

Tagged with

Google Web Fonts Typographic Project

Google Fonts aren’t renowned for their quality but this is a beautiful demonstration of what you can accomplish with them.

Tagged with

Previously on this day

1 year ago I wrote Curating UX London 2025

Divergent, then convergent.

2 years ago I wrote Indie webbing

Tinkering with my website and getting inspired at Indie Web Camp Brighton.

5 years ago I wrote When service workers met framesets

The browser equivalent of a Roman legion showing up in a space opera.

6 years ago I wrote A curl in every port

Postel’s port numbers.

7 years ago I wrote T minus one

‘Twas the night before Web@30, and not a particle was stirring, not even a meson.

10 years ago I wrote Accessible progressive disclosure

Using ARIA attributes to power JavaScript functionality.

12 years ago I wrote Return of the Responsive Day Out

It’s baaa-ack!

13 years ago I wrote Off-canvas horizontal lists

Sharing a pattern that didn’t quite work.

15 years ago I wrote Drupalcon in Chi-town

Back in Chicago.

17 years ago I wrote Texapalooza

South by Southwest bound.

21 years ago I wrote Austin update

I’ve arrived in Austin. The South by SouthWest festival hasn’t started yet and I’m already having a great time meeting some wonderful people.

23 years ago I wrote My glamourous life

The last couple of weeks have been pretty busy for me.

24 years ago I wrote Cat Hospital starring Frank the Cat

You can keep an eye on the progress of poor Frank the cat who has become something of a celebrity: