Part of the jedee wiki — pages written by an AI (Claude Code), supervised by Johan.
OpenType features
A modern font file carries more than one shape per character. OpenType features are named switches inside the file, each a four-letter tag, that substitute or reposition glyphs: liga joins “f” and “i” into one ligature, smcp swaps lowercase for small capitals, onum swaps lining figures for old-style ones. The tags are defined in the OpenType feature registry; which of them a given font implements is up to its designer.
A few are on by default in every browser, because text looks broken without them: kern (kerning), liga (standard ligatures), calt (contextual alternates), ccmp and locl (glyph composition and language-specific forms). Everything else is off until CSS asks for it.
Switching them on
CSS has two levels. The font-variant-* properties name the effect, and are the ones to reach for:
.caps { font-variant-caps: small-caps; } /* smcp */
.figures { font-variant-numeric: oldstyle-nums; } /* onum */
.table { font-variant-numeric: tabular-nums slashed-zero; } /* tnum + zero */
.fraction { font-variant-numeric: diagonal-fractions; } /* frac */
.fancy { font-variant-ligatures: discretionary-ligatures; } /* dlig */(MDN: font-variant-numeric, font-variant-caps, font-variant-ligatures.)
font-feature-settings is the low-level escape hatch for tags with no named property, chiefly stylistic sets (ss01–ss20) and character variants (cv01–cv99), whose meaning differs per font:
.alt { font-feature-settings: 'ss01', 'ss10'; }⚠ font-feature-settings is one property holding a list, so a later declaration replaces the whole list rather than adding to it. A rule setting 'ss01' on a child silently turns off a 'ss10' its parent set. The font-variant-* properties don’t have this problem, since each controls its own features.
⚠ Asking for a feature the font lacks does not fail visibly. For small caps the browser synthesizes them, shrinking the capitals, which gives thin, pale letters next to real ones; font-synthesis-small-caps: none turns that off. For most other features nothing happens at all. The only way to know what a font can do is to look inside it (fontTools lists a file’s GSUB features) or render every feature on and off.
⚠ Subsetting removes features along with glyphs. A subset keeps a feature’s rules only for the characters it keeps, so small caps exist only for the letters in the subset, and a stylistic set that acts only on dropped characters disappears. With pyftsubset, --layout-features='*' is what keeps features at all; see Font subsetting.
In jedee
The site sets no OpenType features of its own beyond the browser defaults, apart from font-variant-numeric: tabular-nums in two places: the menu’s post counts (global/blocks/main-nav.css:204) and the activity figures (local/activity.css:21). ⚠ Both are no-ops in these fonts: Source Serif and Source Sans already have tabular figures by default, every digit the same advance width (542 units in Serif, 472 in Sans upright, 456 italic). The rules cost nothing and say what the numbers need, so they stay.
What the shipped subsets can do, checked by rendering each feature on and off from the site’s own files (every pair verified by npm run mockups:check to render differently) and by comparing glyph outlines:


dlig replaces English pronouns with a single glyph.Source Serif (source-serif.woff2, Bold 700, 109 characters):
- On by default:
ligacovers ff, fi, fl, ffi, ffl, fj, ffj, ft, fft, so headings get ligatures already. Pluskernandlocl. - Opt-in, working: small caps (
smcpcovers a–z, å ä ö ü and the digits;c2scturns capitals into small caps too), old-style (onum) and proportional (pnum) figures, diagonal fractions (frac, withnumr/dnom), superscript and subscript (sups,subs,sinf), ordinals (ordn), slashed zero (zero), and case-sensitive forms (case, which raises brackets, hyphens and dashes for all-caps text). - Dropped by the subset: the full font’s two stylistic sets, which turn out to be Cyrillic alternates (Bulgarian, and Serbian/Macedonian), with nothing to act on here. The accent-positioning features (
mark,mkmk,ccmp) went too, since the subset has no combining marks.
Source Sans (source-sans.woff2 and -italic.woff2, variable, 206/207 characters):
- On by default:
ligacovers only ff, ft and fft. There is no fi or fl ligature because Source Sans’ f is drawn so it doesn’t collide.ccmpjoins l·l (the Catalan ela geminada). - Opt-in, working: small caps across Latin-1 (
smcp,c2sc),onum,pnum, titling figures (titl),frac,sups/subs/sinf,ordn,zero,case. - Stylistic sets, working:
ss01serifed I,ss02simple a g l,ss03simple a,ss04simple g,ss05simple l,ss06serifed a,ss09capital figures,ss10dotted zero.cv01–cv05andcv17–cv19offer the same alternates one character at a time, andsaltoffers them together. The full font’sss07,ss08andcv06–cv16act only on characters outside the subset and are gone. - Discretionary ligatures (
dlig): þ + at/æt/et becomes the medieval abbreviation ꝥ (“that”), and Þ the same as Ꝥ.hligoffers the same thorn ligatures on their own. And “she” and “he” become one glyph the font namest_h_e_y, “her”, “his” and “hers” another namedt_h_e_i_r: an invented, single character, not the spelled-out word. It is a gender-neutral third-person pronoun, the same idea as Swedish hen, but one that exists only in writing. Designer Sarah Gephart drew it in 2018 as an independent project on Source Sans Pro, set to replace he, she, his, her and hers automatically; Paul Hunt, the Adobe designer of Source Sans, then added it to the family as a discretionary ligature (AIGA Eye on Design). Four punctuation sequences (.-(,.-),!-),?-() are also ligated underdlig; what they are meant for isn’t identified here. Nothing on the site enablesdlig, and turning it on over running text would rewrite every “he” and “she”. - ⚠ Source Sans italic has no small caps at all, in the subset or in the full italic font.
font-variant-caps: small-capson italic text gives synthesized small caps, unlessfont-synthesis-small-caps: noneis set.
One consequence of the fallback faces (Layout shift): Georgia, behind Source Serif, has old-style figures by default, so a heading’s digits change style, not just font, for the moment before the web font arrives.
Raw source: src/_raw/dev-notes/How the fonts' OpenType features were inventoried.md