Skip to content

Instantly share code, notes, and snippets.

@dabrahams
Created December 13, 2021 02:09
Show Gist options
  • Save dabrahams/3c117cee3b8aecfc02885332b7eb1cda to your computer and use it in GitHub Desktop.
Save dabrahams/3c117cee3b8aecfc02885332b7eb1cda to your computer and use it in GitHub Desktop.
Notes on how Keynote lays out text boxes, and translating that into CSS

Line spacing

In keynote, line spacing is specified per-paragraph. Paragraphs are line-wrapped into physical lines.

For now, we're only interested in text boxes where spacing is specified in “lines.”

For a physical line β and a character γ:

  • Dᵧ is the “hhea descender” of γ.
  • Gᵧ is the “hhea line gap” of γ.
  • Aᵦ is the max “hhea ascender” for all characters in β
  • Dᵦ is the min “hhea descender” of all characters in β
  • Eᵦ is the max of Gᵧ-Dᵧ over all characters γ on the line β:
  • Lᵦ is the keynote line spacing in lines.

The distance between baselines i and i+1 is (Lᵢ-1)(Aᵢ - Dᵢ) + Eᵢ + Aᵢ₊₁

Top of text box

The distance from the top of text box to the baseline of line 0 is a constant A₀. Therefore, this distance should be represented by margin-top values on the content of the first non-empty descendant of the text box that is a block element.

Note that there's really no way to account for differences in this value across span-level elements, even using display: inline-block, unless you can be sure that the lines don't wrap.

However, some text boxes, such as headings, aren't expressed in HTML using any embedded block elements. In these cases, the top margin of the absolutely-positioned element can be used to create the top-of-box gap (https:stackoverflow.com/questions/25944865/why-does-margin-top-affect-the-placement-of-an-absolute-div). Fortunately this seems to function exactly as a non-absolutely-posititioned child <p>'s top margin would be used.

Paragraph spacing

Keynote has an absolute paragraph above/below spacing setting that acts roughly like top/bottom margins do in CSS, except that they have no effect at the top or bottom of a text box. These spacing values are added to any line spacing that would ordinarily be in effect across the last/first lines of adjacent paragraphs.

Text boxes

Keynote text boxes rendered in HTML are formatted with position: absolute in order to match placement. Absolutely-positioned elements are not subject to margin collapsing, which means any top margin on the text box's first child, along with the box's own padding, regulates the child's vertical position within the box.

Keynote's “text inset” setting corresponds exactly to CSS padding, and applies to the whole text box, on all sides.

CSS-injected text

Text that is part of the Keynote layout is generated using CSS text injection on ::before and ::after pseudo-elements. Because pseudo-elements don't get their own ::before and ::after elements, “trim” amounts need to be built into their positioning, margins, or padding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment