OpenType-Features: Ligaturen, Kapitälchen und mehr
OpenType Features: Ligatures, Small Caps, and Beyond
Most developers reach for a font file, set font-family and font-weight, and call it done. This approach works, but it leaves a significant portion of the font's capabilities on the table. Modern OpenType fonts are sophisticated systems containing dozens — sometimes hundreds — of alternate glyphs, contextual substitutions, and advanced typographic features. Accessing these features transforms good typography into great typography.
OpenType features are activated in CSS through two mechanisms: the high-level font-variant-* properties and the lower-level font-feature-settings property. Understanding both, and knowing when to reach for each, opens up a dimension of typographic control most web developers have never explored.
What Are OpenType Features?
OpenType is a font format specification developed jointly by Adobe and Microsoft in the 1990s and now maintained as an international standard. Beyond simply encoding character shapes, OpenType fonts can include a rich set of behavioral tables — instructions to the rendering engine about how characters should be substituted, positioned, or combined under various conditions.
These instructions are organized into features, identified by four-letter tags. Common feature tags include liga (standard ligatures), smcp (small capitals), onum (old-style numerals), tnum (tabular numerals), kern (kerning), and ss01 through ss20 (stylistic sets). A font can support any combination of these features, and many professional-quality fonts support dozens.
The feature is only usable if the font has been designed to support it. Enabling font-feature-settings: "smcp" on a font that has no small cap glyphs will produce no visible result — the browser cannot manufacture features the font does not contain. Always check a font's specimen or documentation to see which features it supports before building systems around them.
Google Fonts provides a useful filter for OpenType features on their website, and many font foundry pages include feature demonstrations. For fonts like EB Garamond and Playfair Display, the OpenType feature sets are particularly rich.
Ligatures: Standard, Discretionary, and Contextual
Ligatures are single glyphs that replace two or more adjacent characters that would otherwise collide or create awkward spacing. They are among the most commonly encountered OpenType features and one of the few that should be enabled universally in professional typography.
Standard Ligatures
Standard ligatures address letter combinations where the normal character spacing produces a collision or visual conflict. The most common are:
- fi — the dot of the "i" collides with the top of the "f"
- fl — the curve of the "l" collides with the hook of the "f"
- ff — two adjacent "f" glyphs collide
- ffi — triple collision
- ffl — triple collision
In most OpenType fonts, these ligatures are defined as substitutions that activate automatically. Modern browsers enable standard ligatures by default, but you can be explicit:
/* Explicitly enable standard ligatures (recommended for all text) */
body {
font-variant-ligatures: common-ligatures;
}
/* Low-level equivalent via font-feature-settings */
body {
font-feature-settings: "liga" 1, "clig" 1;
}
The liga tag covers standard ligatures; clig covers contextual ligatures (substitutions that depend on surrounding characters).
Discretionary Ligatures
Discretionary ligatures are more decorative substitutions that are not appropriate for all text but can add typographic elegance in display contexts. Common examples include the "st" ligature (where the top of the "t" connects to the bottom of the "s"), the "ct" ligature, and various swash-form combinations.
/* Discretionary ligatures for display text — use sparingly */
.display-heading {
font-variant-ligatures: common-ligatures discretionary-ligatures;
}
/* Low-level */
.display-heading {
font-feature-settings: "liga" 1, "clig" 1, "dlig" 1;
}
Discretionary ligatures in body text can feel ostentatious and can create uneven text texture. They are best reserved for headlines, pull quotes, and ornamental contexts.
Contextual Ligatures and Alternates
Contextual alternates (calt) are substitutions that activate based on surrounding characters. Unlike fixed ligature substitutions, contextual alternates can change a letter's form based on what comes before or after it — for example, a connecting script font might use different letter ending forms depending on whether the next letter connects.
.script-text {
font-variant-ligatures: common-ligatures contextual;
}
/* font-feature-settings equivalent */
.script-text {
font-feature-settings: "liga" 1, "calt" 1;
}
Small Caps and Case Alternates
Small capitals are a classic typographic refinement — uppercase letterforms drawn at the height of the lowercase x, but with the proportions and weight calibrated for that size. They are used for abbreviations, acronyms, and contextual display where full capitals would appear visually loud.
True Small Caps vs. Faux Small Caps
There are two ways to get small capital letters: true small caps from the font file, and faux small caps generated by the browser by scaling down full capitals.
True small caps are purpose-drawn glyphs. The type designer has redrawn every capital letter at x-height, adjusting stroke weights, proportions, and spacing so the characters look correct at that size. They match the weight and color of the surrounding lowercase text.
Faux small caps are simply the regular capitals scaled down algorithmically. The result is always wrong: the stroke weights become too thin relative to surrounding text, the letter spacing may be off, and the proportions reflect capitals rather than small-caps design.
/* True small caps from OpenType — requires font support */
abbr, .small-caps {
font-variant-caps: small-caps; /* CSS font-variant shorthand */
}
/* Low-level equivalent */
abbr, .small-caps {
font-feature-settings: "smcp" 1; /* Lowercase to small caps */
}
/* All text to small caps: capitals remain caps, lowercase becomes small caps */
.all-small-caps {
font-variant-caps: all-small-caps;
font-feature-settings: "smcp" 1, "c2sc" 1; /* c2sc: caps to small caps */
}
The CSS property font-variant-caps: small-caps without corresponding OpenType support will generate faux small caps. Always verify that the font you are using has true small cap glyphs before relying on this feature. EB Garamond has well-crafted small caps; Inter currently does not include small caps.
Unicase and Petite Caps
Some fonts also offer unicase (mixing upper and lowercase heights) and petite caps (smaller than standard small caps, approximately at the x-height midpoint). These are specialized features found in only a small number of fonts and primarily useful for display purposes.
Tabular vs. Proportional Numbers
Number spacing is one of the most practically important OpenType features for developers, and one of the least commonly controlled. Two feature pairs govern how numerals are spaced:
Proportional vs. Tabular spacing: Proportional numerals (the default in most text fonts) have spacing calibrated to the natural width of each numeral. A "1" takes less horizontal space than an "0". Tabular numerals give every numeral exactly the same horizontal width — so columns of numbers always align vertically.
Old-style vs. Lining figures: Old-style figures (also called text figures) vary in height, with some numerals having ascenders (6, 8) and some having descenders (3, 4, 5, 7, 9). They integrate harmoniously into lowercase text. Lining figures are all the same height (approximately cap height) and sit solidly on the baseline.
/* Proportional old-style figures: best for numbers in running text */
.body-text {
font-variant-numeric: proportional-nums oldstyle-nums;
/* font-feature-settings equivalent: */
font-feature-settings: "pnum" 1, "onum" 1;
}
/* Tabular lining figures: essential for data tables, financial figures */
.data-table td {
font-variant-numeric: tabular-nums lining-nums;
font-feature-settings: "tnum" 1, "lnum" 1;
}
The practical importance of tabular numerals in tables, dashboards, and financial applications cannot be overstated. Without them, columns of numbers that change (think live pricing, percentages, counters) cause constant visual jitter as character widths change with the values. With tabular numerals, columns stay aligned regardless of value changes.
/* Complete numeric formatting for a financial dashboard */
.price-column {
font-variant-numeric: tabular-nums lining-nums;
font-feature-settings: "tnum" 1, "lnum" 1;
font-variant-numeric: slashed-zero; /* Distinguish 0 from O */
}
The slashed-zero value is particularly useful in financial and technical contexts where "0" must be visually distinct from "O". Not all fonts support it, but Source Code Pro and Roboto Mono do among coding fonts, and Inter has it available as a stylistic alternate.
Stylistic Alternates and Sets
Many fonts include alternate versions of specific characters — different forms of "a", "g", "y", or other letters that the designer drew as alternatives to the primary form. These alternates are accessed through two mechanisms:
Stylistic alternates (salt) provide access to individual alternate glyphs for specific characters. A font might have three different forms of the ampersand, or two versions of the lowercase "a".
Stylistic sets (ss01 through ss20) are grouped collections of alternates. A type designer might bundle a set of single-story alternates into ss01, decorative swash variants into ss02, and so on. The naming is arbitrary and font-specific — you must check the font's documentation to know what each stylistic set contains.
/* Enable a specific stylistic set — meaning is font-dependent */
.alternate-a {
font-feature-settings: "ss01" 1; /* Single-story 'a' in some fonts */
}
/* Inter stylistic alternates — specific to Inter's design */
.inter-alternate {
font-feature-settings: "cv01" 1, /* Alternate 'a' */
"cv02" 1, /* Alternate 'g' */
"ss01" 1; /* Various other alternates */
}
Inter in particular has extensive character variant options, documented in its specimen. These include alternate forms for several characters that allow the typeface to shift its aesthetic slightly — from its default contemporary look toward something slightly more classical or technical.
CSS: font-feature-settings vs. font-variant
CSS provides two levels of control over OpenType features, and choosing the right one matters for code quality and maintainability.
font-variant (High-Level, Recommended)
The font-variant-* family of CSS properties provides semantic, readable control over specific OpenType features:
.well-crafted-typography {
/* Ligatures */
font-variant-ligatures: common-ligatures;
/* Numbers */
font-variant-numeric: oldstyle-nums proportional-nums;
/* Small caps */
font-variant-caps: small-caps;
/* Alternate characters */
font-variant-alternates: stylistic-set(1);
}
These properties are more maintainable, more readable, and follow the cascade more predictably. They are the recommended approach for features that have a corresponding high-level property.
font-feature-settings (Low-Level, Escape Hatch)
The font-feature-settings property provides direct access to any OpenType feature by its four-letter tag. It is more powerful but also more fragile:
/* The cascade problem: this overrides all other font-feature-settings */
.problematic {
font-feature-settings: "tnum" 1; /* This DISABLES liga, kern, etc. implicitly */
}
/* Better: include all features you want enabled */
.better {
font-feature-settings: "liga" 1, "kern" 1, "tnum" 1;
}
The major pitfall of font-feature-settings is that it does not cascade like normal CSS properties — it replaces the entire set. If a parent element has font-feature-settings: "liga" 1 and a child has font-feature-settings: "tnum" 1, the child loses the ligature setting rather than adding to it.
The Best Practice
Use font-variant-* properties wherever possible. Fall back to font-feature-settings for features that do not have a high-level equivalent (specific stylistic sets, character variants, and less common features):
/* Recommended approach: combine high-level and low-level */
.body-text {
/* High-level properties for standard features */
font-variant-ligatures: common-ligatures;
font-variant-numeric: proportional-nums oldstyle-nums;
/* Low-level for font-specific features without high-level equivalents */
font-feature-settings: "calt" 1; /* Contextual alternates */
}
.data-table-cell {
font-variant-numeric: tabular-nums lining-nums;
font-feature-settings: "tnum" 1, "lnum" 1; /* Belt and suspenders */
}
OpenType features represent the difference between using a font and using it well. The ligature that prevents a collision, the tabular number that keeps data aligned, the small cap that dignifies an abbreviation — these details aggregate into typography that feels professionally considered rather than merely functional. Most fonts contain far more than most developers ever use. The features covered here are a starting point, not an exhaustive list.
For how OpenType numerals interact with typographic hierarchy and layout, see the Typographic Hierarchy guide. For type anatomy context on specific features like ligatures and terminals, see Type Anatomy 101.
Typography Terms
Try These Tools
Fonts Mentioned
Rasmus Andersson spent years refining this neo-grotesque specifically for computer screens, optimizing letter spacing, x-height, and stroke contrast for high readability at small sizes on digital displays. An optical size axis (opsz) lets the font automatically adjust its design for captions versus headlines, while the weight axis covers the full range from thin to black. It has become the de facto choice for dashboards, documentation sites, and developer tools worldwide.
Source Sans was Adobe's first open-source typeface, designed by Paul D. Hunt as a clean, readable sans-serif for user interfaces, and Source Sans 3 represents its most refined iteration as a fully variable font spanning the weight axis. The humanist construction — drawn from the proportions of Robert Slimbach's calligraphic lettering — lends warmth to what could otherwise be a purely neutral grotesque. Broad script support covering Cyrillic, Greek, and Vietnamese makes it a dependable choice for multilingual documentation and cross-platform UI design.
EB Garamond is Georg Duffner's open-source revival of the sixteenth-century types of Claude Garamond, one of the most influential typeface designers in Western printing history, based closely on the specimen printed by Conrad Berner in 1592. The variable weight axis covers a range from regular to bold, and the family's extensive script support — Latin, Cyrillic, Greek, Vietnamese — makes it unusually versatile for a typeface so deeply rooted in the Renaissance humanist tradition. It brings scholarly elegance and historical authority to book design, academic publishing, and editorial contexts that prize typographic heritage.
Fira Code is a monospace typeface by Nikita Prokopov that extends Mozilla's Fira Mono with a carefully curated set of programming ligatures, turning multi-character sequences like arrows, comparisons, and operators into single fluid glyphs. The variable weight axis (wght) lets developers fine-tune stroke thickness without switching font files, and the face covers Cyrillic, Greek, and extended symbol ranges. It is the go-to choice for code editors and terminal emulators where ligature rendering is supported.