What You Actually Need To Know Before Touching A Font Editor

Type is not a design choice. It is a set of engineering constraints that nobody talks about until their layout breaks at 11pm the night before launch. I have spent fourteen years working with type at production scale, and the thing that keeps surprising people is how little most of us actually understand about what a font file contains. We treat it like a stylesheet with pretty letters. It is not. It is a compiled binary with a metric table, a glyph outline system, kerning pairs, and a dozen optional lookup structures that interact in ways that will quietly ruin your day if you ignore them. At the lowest level, a font is a collection of glyphs. Each glyph has an outline, usually stored as quadratic or cubic bezier curves, wrapped in coordinates relative to an em grid. The em is almost always 1000 units for modern OpenType fonts, sometimes 2048 for CFF2 or variable fonts. That number matters because every single measurement in the file is scaled against it. Line height, cap height, x-height, ascender, descender, bearing, advance width. All of it lives in that grid. If you misread the em size or assume the bounding box equals the advance width, your text will render with either gaps or overlaps depending on the platform. Here is where beginners drop the ball. They look at a glyph and see a shape. You need to see three things simultaneously: the outline path, the horizontal metrics (hmtx table), and the vertical metrics (vmtx or vhea). The outline is what you draw. The hmtx tells the renderer how far to advance the pen after drawing that glyph. The vmtx does the same vertically. When these are out of sync, you get widows, orphans, or entire paragraphs shifting by a pixel on certain browsers. I once spent six hours debugging a layout issue that turned out to be a single font where the nominal width in the font properties did not match the actual advance widths in the hmtx table. The numbers were off by an average of 40 units. Nobody noticed because the visual difference was subtle, but when you had tight justification with no hyphenation allowed, the whole block would buckle.

How Kerning Actually Works

Kerning is not spacing between letters. That is tracking. Kerning is a targeted adjustment applied only to specific glyph pairs. The kerning table (kern in OTF, GPOS in OpenType) stores lookup structures that say: when glyph A precedes glyph B, shift the second glyph left by X units. Simple in theory. Brutal in practice because the lookup algorithm has to handle context, classes, and backwards compatibility all at once. Most designers think kerning is just a list of pairs. It is not. It is a state machine. The renderer builds a kerning lookup, classifies glyphs into groups, and then applies adjustments based on what precedes and follows each glyph. If your font has ligatures, the kerning lookup interacts with the substitution table. If you turn on discretionary ligatures, the kerning values change because the glyph sequence changes. I learned this the hard way when a client complained that their brand font looked "loose" in headlines but "tight" in body text. The issue was that their headline treatment used a small-caps substitution that replaced certain letter pairs, and the kerning table had no entries for those substituted pairs. The fix was adding explicit kerning entries for the small-caps forms, or better yet, disabling automatic kerning for that specific text style and handling spacing manually. There is also the question of font format. TrueType fonts store kerning in a flat table. OpenType fonts store it in GPOS lookups. Variable fonts store it inside the same GPOS structure but allow the adjustments to interpolate along axes. If you are shipping a web font and your kerning looks wrong in Safari but fine in Chrome, check whether the font uses the old flat kern table or the OpenType GPOS format. Safari historically had a bug where it ignored GPOS kerning for certain script types. The workaround was converting the kerning to the legacy format or using CSS font-feature-settings to explicitly enable the right lookups.

Metrics That Will Break Your Layout

The ascender and descender values in a font are not the same as the visual extent of the glyphs. The ascender marks the theoretical top of a lowercase letter like h or l, but many fonts have ascenders that extend well above that value for capital letters or diacritical marks. The descender marks the bottom of g or y, but some fonts descend much further for italic forms or tied glyphs. If you are calculating line height based on ascender minus descender, you will get wrong results unless the font designer explicitly set those values to match the actual glyph bounds. Cap height is another trap. Some fonts define cap height as the distance from the baseline to the top of a capital H. Others use the top of a capital I, which is slightly lower because I has no serifs extending above its main stem. The difference is usually 20 to 40 units in a 1000-unit em grid, which translates to roughly 0.5 to 1 percent at typical display sizes. Barely noticeable in isolation. Devastating when you are aligning multiple typefaces in a heading hierarchy and expecting them to sit on the same visual plane. Here is something most people do not know: the typo tables in OpenType exist specifically to separate the typographic metrics from the legacy OS/2 metrics. The OS/2 table carries WinAscent and WinDescent values that were designed for Windows text rendering in the 1990s. They are often wildly inaccurate compared to the actual glyph bounds. macOS and modern browsers prefer the typo tables. If you are building a typeface or modifying an existing one, always set both the OS/2 and typo tables, and make sure they agree within a reasonable tolerance. A mismatch of more than 100 units between WinAscent and typo table ascent will cause inconsistent line heights across platforms.

Get the Full Details

The Anatomy Of Type The Anatomy Of Type By Stephen Coles An Online
The Anatomy Of Type The Anatomy Of Type By Stephen Coles An Online

OpenType Features And The Hidden Complexity

OpenType features are not optional decorations. They are substitution and positioning lookups that run during text shaping. Ligatures, alternates, swashes, contextual forms, fraction substitution, oldstyle figures, small caps. Each one is a feature tag with a lookup table behind it. The problem is that not all renderers support all features, and the ones that do support them often implement them differently. Small caps is the classic example. A properly designed small-caps set replaces lowercase glyphs with scaled-up capitals that match the x-height. But many fonts fake small caps by simply scaling down the regular capitals. The result looks wrong because the scaled-down capitals have incorrect stroke weight and spacing. I encountered this when a publishing client wanted a consistent typographic voice across a multi-volume series. The reference font had real small caps in some languages but fake small caps in others, and the inconsistency was only visible when you put the books side by side. The workaround was swapping to a different font family entirely for those language variants, even though it meant redesigning the style guide. Ligatures are another minefield. Standard ligatures like fi and fl are usually safe. Discretionary ligatures are not. Some fonts include decorative ligatures that look beautiful in display text but destroy readability at small sizes. I have seen fonts where the discretionary ligature for "ct" looks like a single connected glyph that is nearly illegible at 12pt. The fix is to never enable discretionary ligatures by default and only turn them on for large display sizes where the reader has time to process the shape.

Variable Fonts And The New Reality

Variable fonts changed everything. Instead of shipping a weight as a separate font file, you ship one file with a continuous axis. Weight, width, slant, optical size. The axis values are normalized between 0 and 1 internally, then mapped to user-space values through a mapping table. This is elegant until you encounter a font where the axis range is incomplete or the interpolation breaks down at the extremes. I worked on a project where the variable font designer only filled in keyframes at weight 400 and weight 700, leaving the interpolation between those points undefined for certain glyphs. The result was that at weight 550, some characters would jump unexpectedly rather than interpolate smoothly. The workaround was adding explicit keyframes at intermediate weights, which required opening the font in a proper editor and manually adjusting the control points. It took about three hours for a font with 200 glyphs. Not impossible, but something nobody warns you about. Optical size is the axis that matters most for readability. A font designed for 12pt body text should not be used at 72pt display size without switching to the corresponding optical size variant. The difference is in stroke contrast, serif proportion, and x-height. At small sizes, low contrast and larger x-height improve legibility. At large sizes, high contrast and smaller x-height look more refined. If your variable font includes an opsz axis, use it. If it does not, accept that you are making a compromise.

Practical Advice For Working With Type At Scale

Stop relying on the default line height. Most fonts ship with a line height that assumes a certain amount of headroom, but that assumption varies wildly between typefaces. A font with large descenders and a low ascender will need different spacing than a font with compact metrics. Calculate line height based on your actual glyph bounds, not the font's nominal values. The formula is simpler than it sounds: measure the distance from the lowest descender to the highest ascender across your most common characters, then add 10 to 20 percent for breathing room. Test your fonts at the sizes you will actually use them in. A font that looks fine at 16pt in your editor may render poorly at 14pt on a low-DPI screen due to subpixel alignment issues. The Fixman tool or ttfautohint can help, but they are not magic. Run them and then inspect the output visually at the target sizes. If characters look fuzzy or misaligned, adjust the hinting strategy or switch to a different rasterization method. When shipping web fonts, subset aggressively. A full Latin font with all diacritical marks and OpenType features can easily exceed 500KB. If your content only uses basic Latin characters, a subsetted font can be under 50KB. Use tools like fonttools or pyftsubset to remove unused glyphs and features. The tradeoff is that you lose the ability to render characters that appear later in dynamic content, so build a fallback system that loads additional subsettings on demand if needed.

The Anatomy Of Type The Anatomy Of Type By Stephen Coles An Online
The Anatomy Of Type The Anatomy Of Type By Stephen Coles An Online

Keep a reference font in your workflow that you trust completely. Not because it is the best font, but because you know its metrics, its quirks, and its limitations inside out. I use Source Sans Pro as my baseline because its metrics are well-documented, its OpenType support is solid, and its variable font axis is complete. When I need to evaluate a new font, I compare its metrics against Source Sans Pro in the same layout context. Differences become obvious immediately instead of hiding in the details.