
Ascenders, Descenders, and Baselines: The Anatomy of a Letterform
- Sajjad
- Typography
- 01 Oct, 2026
You align an icon next to a button label and it looks a pixel or two too high, no matter how you adjust vertical-align. You set overflow: hidden on a heading for a reveal animation and the tails of the g and y get chopped off. You switch typefaces and every badge in the UI suddenly has its text sitting off-centre. These bugs all come from the same place: the invisible lines and measurements that every font is built on, and how CSS uses them to lay out text.
This article walks through the anatomy of a letterform — the vertical metrics such as baseline, x-height, cap height, ascenders, and descenders, and the structural parts like stems, bowls, counters, and terminals. It then shows how those metrics map to font files and CSS, so you can fix alignment problems, compare typefaces, and talk to designers using the same vocabulary.
Why Letterform Anatomy Matters for Developers
Type anatomy is not just design vocabulary. It explains concrete layout behaviour:
- Why text never looks vertically centred in a box with equal padding.
- Why descenders get clipped by tight
line-heightandoverflow: hidden. - Why two fonts at the same
font-sizelook different sizes. - Why fallback fonts cause layout shift.
- Why some typefaces are more legible at small sizes than others.
It also gives you precise words for feedback. "The descenders are too short for that line height" is more useful than "it looks cramped."
The Vertical Metrics: Lines Every Letter Sits On
Every font is designed on a set of horizontal guidelines. From bottom to top:
| Line / zone | What it is |
|---|---|
| Descender line | The lowest point of descenders, as in g, j, p, q, y |
| Baseline | The line most letters sit on |
| X-height (mean line) | The top of flat lowercase letters such as x, v, z |
| Cap height | The top of flat capital letters such as H, E, T |
| Ascender line | The top of ascenders in b, d, f, h, k, l, often above cap height |
Baseline
The baseline is the invisible line that letters rest on. It is the most important line in typography because it is what aligns text across fonts, sizes, and elements. When you put two different fonts side by side in the same line, CSS aligns them on their baselines by default (vertical-align: baseline).
Round letters like o, c, and s dip slightly below the baseline. This overshoot makes them look like they sit on the line, because curves touching a line look smaller than flat strokes touching it.
X-Height and the Mean Line
The x-height is the height of lowercase letters without ascenders or descenders. The line at the top of the x-height is called the mean line or midline. Because most text is lowercase, x-height has the biggest effect on how large text appears. It gets its own deep dive in what x-height is and why it matters.
Cap Height
The cap height is the distance from the baseline to the top of flat capitals like H. It is usually a bit lower than the ascender line, so lowercase d and l stand slightly taller than capitals in many typefaces. That difference stops capitals from overpowering mixed-case text.
Ascenders
An ascender is the part of a lowercase letter that rises above the x-height: the stems of b, d, h, k, l, the top of f, and the dot-and-stem of t (though t is typically shorter). Ascenders give words distinctive outlines, which helps readers recognize words at a glance.
Descenders
A descender is the part of a letter that drops below the baseline: the tails of g, j, p, q, and y. In some typefaces, capital J and Q also descend. Descenders also contribute to word shape and need room — tight line heights make descenders from one line collide with ascenders in the next.
The Em Box
All of these lines sit inside the em box (or em square), the invisible design grid that font-size sets. A 16px font has an em box 16px tall. The type designer decides where the baseline, x-height, and cap height fall inside it. Ascenders and descenders, and especially accents on capitals like É, can even extend outside the em box.
Structural Parts of a Letter
Beyond vertical metrics, letters are built from recurring parts. You do not need to memorize every term, but these come up constantly in type selection and feedback.
Strokes and Stems
- Stem: The main vertical (or diagonal) stroke of a letter, such as the upright in
l,b, orH. - Stroke: Any line that forms part of a letter. Stroke contrast is the difference between thick and thin strokes; high-contrast faces like Bodoni have dramatic variation, low-contrast faces like Roboto are nearly uniform.
- Crossbar (bar): The horizontal stroke in
A,H,e,f, andt. - Arm: A horizontal or upward stroke attached at only one end, as in
E,F,K, and the top ofT. - Leg: A downward stroke attached at one end, as in
KandR. - Spine: The central curved stroke of
Sands. - Shoulder: The curved stroke coming off a stem, as in
h,m, andn.
Enclosed and Open Spaces
- Bowl: A curved stroke that encloses a space, as in
b,d,o,p, andq. - Counter: The space inside a letter, either fully enclosed (the inside of
o) or partly enclosed (the inside ofcorn). Large, open counters improve legibility at small sizes. - Aperture: The opening of a partially enclosed counter, as in
c,e,a, ands. Open apertures (Source Sans 3, Fira Sans) stay legible at small sizes; closed apertures (Helvetica) look tidy but can makee,c, andoharder to distinguish. - Eye: The enclosed counter of the lowercase
e.
Endings and Details
- Terminal: The end of a stroke that does not have a serif, such as the top of
a,c,f, orr. Terminals can be flat, angled, rounded, or ball-shaped. - Serif: The small finishing stroke at the end of a stem. Covered in detail in serif vs. sans-serif fonts.
- Bracket: The curved transition between a serif and the stem.
- Spur: A small projection off a stroke, often at the bottom right of
Gorb. - Ear: The small stroke at the top right of a double-storey
g. - Link (neck): The stroke connecting the upper bowl and lower loop of a double-storey
g. - Loop: The lower enclosed part of a double-storey
g. - Tail: The descending stroke of
Q, or the decorative end ofR,K, ory. - Apex and vertex: The top point of
A(apex) and the bottom point ofV(vertex).
Single- and Double-Storey Letters
The lowercase a and g come in two forms:
| Letter | Double-storey | Single-storey |
|---|---|---|
a | Bowl with a curved top arm (Roboto, Georgia) | Simple bowl and stem (Futura, many italics) |
g | Upper bowl, link, and lower loop (Times, Garamond) | Bowl with an open tail (Helvetica, Inter) |
Single-storey a looks closer to handwriting, which is why some fonts aimed at early readers and dyslexic readers use it. Some variable and OpenType fonts let you switch between forms with stylistic sets via font-feature-settings.
How Font Metrics Map to the Font File
The vertical lines above are stored as numbers in a font's tables, in font units relative to units per em (UPM), commonly 1000 or 2048.
| Table / field | Meaning |
|---|---|
head.unitsPerEm | Size of the em box in font units |
OS/2.sxHeight | X-height |
OS/2.sCapHeight | Cap height |
hhea.ascender / hhea.descender | Ascent and descent used by macOS and many browsers |
OS/2.sTypoAscender / sTypoDescender | Typographic ascent and descent |
OS/2.usWinAscent / usWinDescent | Clipping bounds used on Windows |
hhea.lineGap / OS/2.sTypoLineGap | Extra space the font suggests between lines |
Which set a browser uses depends on the platform and the USE_TYPO_METRICS flag in the font. Inconsistent metrics between these fields are a common reason the same font sits differently on Windows and macOS.
You can inspect them with fonttools:
pip install fonttools
python - <<'EOF'
from fontTools.ttLib import TTFont
f = TTFont("SourceSerif4-Regular.ttf")
upm = f["head"].unitsPerEm
hhea, os2 = f["hhea"], f["OS/2"]
def em(v):
return f"{v} ({v / upm:.3f} em)"
print("unitsPerEm ", upm)
print("cap height ", em(os2.sCapHeight))
print("x-height ", em(os2.sxHeight))
print("hhea ascender ", em(hhea.ascender))
print("hhea descender ", em(hhea.descender))
print("typo ascender ", em(os2.sTypoAscender))
print("typo descender ", em(os2.sTypoDescender))
print("win ascent ", em(os2.usWinAscent))
print("win descent ", em(os2.usWinDescent))
print("line gap ", em(hhea.lineGap))
print("USE_TYPO_METRICS", bool(os2.fsSelection & (1 << 7)))
EOF
How CSS Uses These Metrics
The Content Area and Line Box
When the browser lays out a line, it uses the font's ascent and descent metrics to determine the content area — the region from the top of the tallest possible glyph to the bottom of the deepest descender. Then it applies line-height, splitting the extra space (the half-leading) above and below. The details are in what leading is and how to set line height.
Because ascent is usually larger than descent, and both include space for accents, the visible letters rarely sit in the exact middle of the line box. That is why text in a button with equal top and bottom padding often looks slightly high or low.
Trimming to Cap Height and Baseline
The text-box property trims the extra space above and below text to specific metrics, making optical alignment much easier. It is supported in Chromium-based browsers and Safari:
.button {
padding-block: 0.75rem;
line-height: 1.2;
text-box: trim-both cap alphabetic;
}
cap trims the top to the cap height and alphabetic trims the bottom to the baseline, so the visible text is centred between equal padding. You can also use ex to trim to the x-height for lowercase-only labels.
Aligning to the Baseline
Inline elements align to the baseline by default. To align icons with text, size and offset them in font-relative units:
.icon-inline {
width: 1em;
height: 1em;
vertical-align: -0.125em; /* drop slightly so the icon centres on the x-height and cap height */
}
For flex and grid layouts, align items by their first baseline:
.price-row {
display: flex;
align-items: baseline; /* labels and large prices share a baseline */
gap: 0.5rem;
}
Baseline alignment is what makes a large "$49" and a small "/month" look like they belong together.
Font-Relative Units
CSS exposes several metrics as units:
| Unit | Equals |
|---|---|
em | The font size (em box height) |
ex | The x-height of the current font |
cap | The cap height of the current font |
ch | The advance width of the 0 glyph |
ic | The advance width of the CJK "water" ideograph |
lh | The computed line height of the element |
.badge-dot {
width: 1cap;
height: 1cap;
border-radius: 50%;
}
Avoiding Clipped Descenders
Animations that reveal text by sliding it inside a container with overflow: hidden often clip descenders and accents. Give the container room below the baseline:
.reveal-line {
overflow: clip;
padding-block-end: 0.15em; /* room for descenders */
margin-block-end: -0.15em; /* keep the layout unchanged */
}
Also avoid line-height: 1 on multi-line text in fonts with long descenders; descenders from one line can touch ascenders on the next.
Overriding Metrics for Fallbacks
The @font-face descriptors ascent-override, descent-override, and line-gap-override replace a font's metrics. Combined with size-adjust, they let a local fallback mimic a web font's vertical metrics so the swap does not shift the layout:
@font-face {
font-family: "Source Serif Fallback";
src: local("Georgia");
size-adjust: 96%;
ascent-override: 95%;
descent-override: 30%;
line-gap-override: 0%;
}
Derive the values by comparing the metrics of both fonts, or let next/font compute them for you automatically.
Using Anatomy to Evaluate Typefaces
When comparing fonts for a project, look at:
- X-height relative to cap height. Larger x-heights read better at small sizes.
- Ascender and descender length. Longer extenders give more distinctive word shapes but need more line height.
- Aperture. Open apertures help small text and low-vision readers.
- Counter size. Generous counters stay clear when text is small or bold.
- Distinct letterforms. Check
Il1,O0,rnvsm, andb d p qfor clarity. - Terminal style. Rounded terminals feel friendly; sharp or angled terminals feel crisp or formal.
- Stroke contrast. Low contrast survives small sizes; high contrast suits large display text.
Letterform Anatomy FAQ
The baseline is the invisible line that most letters sit on. Descenders drop below it and round letters overshoot it slightly. CSS aligns inline text and elements on the baseline by default, and flexbox and grid can align items by their first baseline.
Cap height is the height of flat capital letters such as H. Ascender height is the height of tall lowercase strokes in letters such as b, d, and l. In many typefaces ascenders are slightly taller than capitals so that capitals do not overpower lowercase text.
Usually because the container has overflow hidden or clip with a tight line-height, so the area below the baseline falls outside the box. Add a little bottom padding in em units, increase line-height, or remove the overflow clipping on text that wraps.
A counter is the space inside a letter, either fully enclosed as in o and b, or partially enclosed as in c and n. Large, open counters help letters stay legible at small sizes and in bold weights.
Fonts reserve space above cap height for accents and below the baseline for descenders, and ascent and descent are usually unequal. The text box is therefore not centred on the visible letters. The text-box property with trim-both cap alphabetic trims that space for true optical centring.
The em box is the invisible square design space every glyph in a font is drawn within. The CSS font-size property sets its height. Where the baseline, x-height, and cap height fall inside it is decided by the type designer, which is why fonts at the same size can look different.
Conclusion
Every letterform is built on a set of invisible lines — baseline, x-height, cap height, ascender, and descender — inside an em box whose height is all that font-size actually sets. On top of those lines sit structural parts like stems, bowls, counters, apertures, and terminals, which together determine a typeface's personality and its legibility at different sizes.
For web developers, this anatomy explains real layout behaviour: off-centre button labels, clipped descenders, mismatched fallback fonts, and misaligned icons. Inspect font metrics with fonttools, align with baselines and font-relative units like ex and cap, trim with text-box where supported, and override fallback metrics to prevent layout shift. Knowing the parts of a letter turns vague "it looks off" feedback into specific, fixable problems.
Here are some useful references for going deeper on letterform anatomy:
- Google Fonts Knowledge: Glossary — illustrated definitions of baseline, ascender, counter, aperture, and more.
- Microsoft Typography: OS/2 table specification — the fields that store x-height, cap height, and vertical metrics.
- MDN Web Docs: vertical-align — how inline content aligns to the baseline and other metrics.
- MDN Web Docs: ascent-override — overriding font metrics in
@font-face. - W3C: CSS Inline Layout Module Level 3 — the specification behind
text-box, baselines, and line box construction.


