Vertical Rhythm (and Alignment) Elika J. Etemad aka fantasai W3C CSS Working Group Invited Expert

Typographer’s Line Placement Model

Goal: Look pretty.

Tools: Measure and adjust.

Top line visually aligns with other things.

Space lines for pleasant reading and to accommodate ascenders/descenders/superscripts/subscripts/ruby.

Consistent baseline-to-baseline spacing creates vertical rhythm.

If your stuff overlaps it’s your fault.

So review and tweak your things before you print them!

CSS Line Box Model

Goal: Don't overlap content.

Tools: Boxes.

1. Put a bunch of stuff on a line.

2. Draw a box around it.

3. Stack up the line boxes.

3. Stack up the line boxes.

4. All done!

Vertical Rhythm

Intra-Paragraph + Inter-Paragraph + Interrupts

Intra-Paragraph Spacing

Fixing the Line Layout Model

Goal: Make typographers happy. Also, don't overlap the content.

CSS Line Layout Today

What are the sizes?

Sizes found from font metrics

It could be so simple...

Identical font-size, varying font-family

Identical font-size, varying font-family

line-height: # | len | % | normal

line-height: 1.5;
/* 1.5 × font-size */


line-height: 1.5

Why half-leading instead of line gaps?

Base Case: Paragraph of Text, No Font Changes

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

line-height: 1.2

Complication #1: Varying Font Families

line-height: 1.5

line-height: 1.5

line-height: 1.5

Small Wins: Ignoring Fallback Font Metrics

My name is 艾俐俐.

“The first available font is defined to be the first available font that would match the U+0020 (space) character.”

line-height: normal

Happiness is Rare

Fixing Intra-Paragraph Spacing

How to Have Perfect Rhythm

How to Have Perfect Rhythm

Redefining “fit within a line box”

container ← item

Defining the container

Safe Model
Grow if item overflows root line-height.
Sparse Model
Grow if item overflows root line-height + 1/2 line gap.
Absolute Model
Ignore all inline contents. Bigger items always overflow.

Defining the item

  1. Leading Box Model
  2. Margin Box Model?
Content Area
Content Area

Content Area = Font Height Area

Old Model

New Normal?

line-sizing: legacy | normal

Do what CSS2.1 says
TBD! (Help us D?)

</Intra-Paragraph Spacing>

Inter-Paragraph Spacing!


p { margin: 1em 0; }


p { line-height: 1.5em; margin: 1.5em 0; }


p { line-height: 1.5em; margin: 1lh 0; }

Interrupting the Rhythm

Strict Rhythm...

Strict Rhythm...

Strict rhythms are important for multicol

Loose Rhythm...

Block Step Sizing

block-step-size: <length>

Requires used height = n × <length>, for an integer n

block-step-insert: margin | padding
block-step-align: auto | center | start | end

What happens at page/column breaks?

</Inter-Paragraph Spacing>

Trimming Text

Delete the top margin...

Add negative margin???


OpenType metrics

leading-trim-over: normal | text | cap | ex | ideographic
leading-trim-under: normal | text | alphabetic | ideographic
h2 { leading-trim: cap; }
h2 { leading-trim: cap; }
h2 { leading-trim: cap; }
h2 { leading-trim: cap; }

I thought this was a World-Wide Web?

Your metrics are bad, and you should feel bad.

Open Questions

Vertical Alignment

unaligned text

match baselines, then shift

match baselines, then shift

But which baseline?

In a well-designed mixed-script font, the glyphs are positioned in the coordinate space to harmonize with one another when typeset together. The baseline table is then constructed to match the shape of the glyphs, each baseline positioned to match the glyphs from its preferred scripts.

dominant-baseline: auto | alphabetic | ideographic | central | mathematical | …
vertical-align: <'alignment-baseline'> || <'baseline-shift>
└ alignment-baseline: baseline | alphabetic | ideographic | central | …
└ baseline-shift: sub | super | <length>

initial-letters: 2;

How to Help