Here's a thing most developers never think about: the font you're reading code in right now is not a passive box of letter-pictures. It's a small program. Every time you type, it runs — taking the raw sequence of characters you entered and deciding, in context, which shapes to actually draw. What you typed and what you see are not the same thing, and a little rule engine inside the font is the reason.
You've probably met one feature of that engine already, even if you didn't know its name: programming ligatures, the trick where = followed by > quietly renders as a single →, or != becomes a crisp ≠. That's the font noticing a pattern and substituting a different glyph. But ligatures are the loud, slightly divisive example. There's a quieter, cleverer one — built on the exact same machinery — that solves a problem monospaced type has had since the typewriter, and almost nobody notices it's happening. It's called texture healing, and once you see it, you can't unsee it.
Fonts run code: OpenType in one minute
Modern fonts are built on OpenType, and tucked inside an OpenType font is a set of features — rules that transform glyphs based on context. The relevant machinery is called GSUB (glyph substitution): a table of "when you see this sequence of glyphs in this situation, draw those glyphs instead." When your editor or browser lays out text, a shaping engine walks the characters and applies these rules.
Two feature tags matter for our story. liga (standard ligatures) is what merges f + i into a single fi in body text, and in coding fonts powers the =>-to-arrow substitutions. calt (contextual alternates) is the more general one: it swaps a glyph for an alternate version depending on its neighbors. Both are just rules the font author wrote and shipped inside the file. The font isn't storing one picture per letter; it's storing letters plus a program for arranging them. Texture healing is a program written in calt.
What "the font runs code" actually means
It's worth making this concrete, because it's the foundation of everything else. When text gets drawn, the characters don't go straight to glyphs one-to-one. A shaping engine sits in between — HarfBuzz is the open-source one that powers Chrome, Firefox, Android, and a long list of editors and terminals — and its job is to turn a string of Unicode characters plus a font into a sequence of positioned glyphs. As it does, it executes the font's OpenType features.
Those features split across two tables. GSUB (substitution) changes which glyphs you get — ligatures, contextual alternates, texture healing. GPOS (positioning) changes where they go — most famously kerning, the tiny per-pair nudges that tuck an A under a V. Every time a line of text renders, the engine runs both. So the font genuinely is executing a small program against your text, every keystroke, and "what you typed versus what you see" is the gap that program fills.
Here's the detail that sets up texture healing perfectly: monospaced fonts don't kern. Kerning adjusts spacing per pair, but monospace's whole promise is that every glyph keeps the same fixed advance — so the usual GPOS tool for fixing rhythm is off the table by definition. Texture healing is, in effect, the monospace-legal substitute for kerning: it can't move the columns, so instead it swaps the glyphs.
The problem monospace was born with
To see what healing fixes, you have to appreciate the strange bargain monospace makes. In a monospaced font, every character occupies exactly the same horizontal slot — the same advance width. An i gets the same column as an m. This is a feature, not an accident: it descends from typewriters and terminals, and it's why code lines up into neat columns, why an ASCII table renders straight, why your cursor math always works.
But it fights against something typographers care about deeply: even color. Set a block of text, squint at it, and you want a uniform gray — no clumps of ink, no rivers of white. Monospace makes that hard, because real letters aren't the same width. Force a skinny i or l into a wide slot and it floats in an ocean of whitespace. Force a wide m or w into the same slot and it gets cramped, its strokes squeezed together. The result is uneven texture: thin spots and dense spots scattered through otherwise tidy code.
Proportional fonts — the ones this paragraph is set in — fix this the obvious way: they give each letter exactly the width it wants, i narrow and m wide. Even color, beautiful rhythm. But you lose the grid. Columns don't align, an i and an m no longer sit under each other, and the whole reason you wanted monospace for code evaporates. So for decades the choice looked binary: the grid or the rhythm, pick one.
Texture healing: keep the grid, move the ink
Texture healing — pioneered for monospace by Lettermatic in GitHub Next's Monaspace type family — refuses the binary. Its insight is that the advance width and the drawing inside it are two separate things. You can keep every column exactly the same width (the grid is sacred) while changing where, within that column, the ink actually sits.
So the font sorts its glyphs into two camps:
-
Glyphs that can give space — skinny characters like
i,l,j, and most punctuation, which have slack to spare inside their slot. -
Glyphs that need space — wide characters like
mandw, which feel cramped in a standard slot.
When a needy glyph lands next to a generous one — a texture conflict — the font swaps in an alternate that reaches into the neighbor's slack. An m sitting beside an i is redrawn slightly wider, leaning into the breathing room the i wasn't using. Crucially, the advance width never changes: the body of the glyph stays the same size, only the drawing inside it shifts and stretches. The column grid is untouched; the ink is just redistributed to even out the color.
Mechanically, the font carries positional variants of each glyph — an m.left, m.right, and m.both (wider, leaning left, right, or both ways), and i.left / i.right (the skinny glyph nudged to one side to donate its space cleanly). A calt rule detects the conflicting pair and substitutes the right variant on each side. Type mill and the m heals against the i; type filming and the lm pair resolves; winning smooths its wi. You didn't do anything. The font did.
The punchline: it's ligatures' engine, doing something humbler
Here's the part that ties the whole thing together. Texture healing isn't a separate, exotic technology bolted onto the font. It is built on the very same calt machinery as programming ligatures. Ligatures use contextual substitution to merge glyphs (= > → →); texture healing uses contextual substitution to swap in positional variants (m → m.left). Same rule engine, same GSUB table, two different jobs.
That has a delightful practical consequence: in a font that supports both, turning on contextual alternates turns on texture healing for free. It rides along with the feature you may already have enabled for ligatures. And it makes a clean philosophical point about what's actually happening when you type — your font is constantly running little substitution programs on your behalf, and ligatures were just the flashy demo. Healing is the same idea applied with restraint.
The OpenType features you can actually flip
Because all of this is just OpenType features, you control it with feature tags. A coding font like Monaspace exposes several; here's what the common ones do:
| Feature tag | What it does |
|---|---|
calt |
Contextual alternates — this is what enables texture healing (and other neighbor-aware swaps) |
liga |
Standard ligatures — the =>-to-arrow style merges |
ss01–ss10
|
Stylistic sets — groups of coding ligatures by kind (e.g. equals-related, arrow-related), so you can turn families on or off |
cvNN |
Character variants — alternate shapes for individual glyphs (a different g, a slashed zero), often with a numeric value |
Trying it yourself
The font to reach for is Monaspace — it's free under the SIL Open Font License, and it's actually a superfamily: five metrics-compatible families (Neon, Argon, Xenon, Radon, Krypton) that span styles from neo-grotesque to a near-handwriting look, all on identical metrics so you can mix them line to line without anything shifting. Texture healing is its headline trick.
In VS Code, the features live in one setting you have to edit as JSON (it isn't in the graphical settings UI):
{
"editor.fontFamily": "Monaspace Neon",
"editor.fontLigatures": "'calt', 'liga', 'ss01', 'ss02', 'ss03'"
}
calt is the one that matters for healing; liga and the ssNN sets are the coding ligatures, which you can include or drop to taste. If you dislike ligatures but want the spacing benefit, you can enable calt and leave liga off — healing without the arrow-merging. In CSS, the same control is font-feature-settings: "calt" 1; (or the friendlier font-variant-ligatures), so the effect works on the web too, anywhere the shaping engine honors the feature.
What to expect — and what not to
Set your expectations honestly: texture healing is subtle by design. You will probably not look at a healed line and gasp. That's the point — good typography is felt more than seen. What you notice is an absence: the code looks a little calmer, the thin-and-clumpy unevenness is gone, and your eye stops snagging on the gaps without quite knowing why. If you want to see it plainly, type a word full of conflicts like mill or filming and toggle calt on and off; the shift is small but real.
A few honest boundaries. It needs calt support — universal in browsers and modern editors, but in code editors you usually have to switch it on yourself, as above. It's also, for now, specific to fonts that implement it: Monaspace pioneered texture healing for monospace, so don't expect your existing favorite coding font to do it just because it has ligatures — the two features are independent. Ligatures are everywhere; healing is not.
And there's a reason healing is uncontroversial where ligatures famously aren't. Ligatures change what characters look like — a merged === glyph isn't the three equals signs you typed, which is exactly why some developers turn them off (you can misread or mis-edit them). Texture healing never touches glyph identity. An m is still unmistakably an m; only its spacing moved. Nothing is hidden or merged, so there's no readability tax to pay. It's a pure win in a way ligatures aren't, which is probably why it can afford to be invisible.
The font is full of these little programs
Once you see texture healing as a program, you start noticing how many others are running. Several are things developers actively want:
-
Tabular figures (
tnum). Many fonts ship two sets of digits: proportional ones for prose and tabular ones where every digit is the same width, so columns of numbers line up. If you've ever had a dashboard's figures jitter as they update, you wanted tabular figures and didn't know to ask. -
Slashed or dotted zero. The classic "is that a zero or an O?" fix in coding fonts is usually a character variant (
cvNN) or stylistic set you can toggle — a glyph swap, same family of feature as everything here. -
Fractions (
frac) that turn1/2into a proper ½, and case-sensitive forms that lift punctuation when it sits between capitals. - Whole writing systems. The same engine does the heavy lifting for scripts that require context: Arabic letters change shape depending on their position in a word (initial, medial, final), and Indic scripts reorder and combine clusters. For those languages, "the font is a program" isn't a cute framing — text is simply unreadable without the substitutions.
Texture healing sits comfortably in that company: one more contextual rule, written for a problem most people never articulated.
A typeface that's really a function: variable fonts
There's one more sense in which your font is a program, and Monaspace leans on it. Its families are variable fonts — a single file that doesn't store one fixed weight or width, but a set of master designs plus axes (weight, width, slant, optical size) that the renderer interpolates between on demand. Ask for weight 437 and the font computes the outline; it's a typeface expressed as a function you evaluate, not a drawer of pre-baked styles. That's also what lets Monaspace's five families stay metrics-compatible: they're built on shared axes and a shared grid, so you can switch from one to another mid-document and nothing shifts. A font that computes its own letterforms at render time is about as literal as "fonts are programs" gets.
The bigger idea
Texture healing is a lovely thing on its own, but the reason it's worth knowing goes past one clever font feature. It's a reminder that the most invisible tool in your day — the typeface rendering every character you read and write — is quietly doing engineering on your behalf. A font isn't a folder of letter images; it's a little rule engine, and OpenType is its instruction set. Ligatures, contextual alternates, stylistic sets, kerning, the way Arabic letters join or Indic clusters reorder — these are all programs, running invisibly every time text is drawn. Texture healing just happens to be one of the most elegant: a fix for a fifty-year-old compromise, achieved not by abandoning the grid but by teaching the letters to share. The next time your code "just looks nice," consider that the font might be doing more work than you are.
Top comments (0)