Text and fonts

Bundle your fonts, size text from the frame height, and learn which text the checks read and which they skip.

Text in a film has two rules. A font must load from a file in the film folder. A line that the viewer reads must be big enough. This page lists the verb that gives you fonts and the text checks that run on a draftA draft is a fast render at half size and 30 fps, with sound, made by vawe dev.. It also lists the marks that tell the checks a text is texture.

Fonts

The renderer waits for document.fonts, not for the network. Bundle every face in films/<name>/assets/ and load it with @font-face. A font that the page loads from the network is not waited for.

bin/vawe fonts prints the free faces (OFL) that vawe carries, one line each, with the file to copy:

bin/vawe fonts
Geist | variable 100-900 | assets/fonts/Geist.woff2
IBM Plex Mono | 400 | assets/fonts/IBMPlexMono-400.woff2
...

Copy the file into films/<name>/assets/ and write the face:

@font-face {
  font-family: "Geist";
  src: url("assets/Geist.woff2") format("woff2");
  font-weight: 100 900;
}

If a listed file is not in assets/fonts, fetch it with node generators/media/fonts.mjs. The flag --system lists the faces installed on your machine, with a local() name. Use them only in a film that you render yourself. Never copy or commit the font file.

What the renderer does with a font

what happenswhat you see
A face has the status error after load.The render stops with font <family> failed to load: fix its src or remove the @font-face.
A face is still loading after 10 s.The seek stops with font still loading after 10000 ms and the names of the families.
A file that the page needs is not in assets/fonts.The first error line adds the node generators/media/fonts.mjs line.

Size text from the frame height

Write sizes with --vh, so the text keeps its share of the frame in every aspectThe aspect is the width-to-height ratio of a film, such as 16:9, 9:16 or 1:1..

.line { font-size: calc(var(--vh) * 0.08); }

--vh is the frame height in pixels, with the unit. The draft check advises when a text is taller than the frame or under 0.2% of it. This is the sign of a size that reads --vh as 1vh.

The text checks

The bin/vawe dev draft check samples the text of the page every 0.5 s (10 to 40 samples). It reads each visible line: a line shows when it has no visibility: hidden, its opacity is above 0.5 and it is inside the frame.

checkwhat it findslimit
readable-text-sizeA held line with a cap height under the floor. The cap height is 0.7 times the font size. A line is held when it stays 0.5 s.6% of the frame height. 3% inside data-ui. 2.5% inside data-chrome.
text collisionTwo different texts that overlap.A quarter of the smaller box. Two texts of different worlds, and a text that travels, are skipped.
text contrastThe text colour against the pixels behind it.4.5:1, or 3:1 for large type.

At 1080p, a cap height of 6% is about 65 px, a font size of about 93 px. Raise the font. Do not shrink the line.

Texture: aria-hidden, data-chrome, data-ui

Some text is not copy to read: a grid of tiny words behind a title, or the labels of a product that you show behind the copy. The text checks can skip it.

markmeaningcap floor
aria-hidden="true"The text is texture. The checks skip it.None, when it is texture by measure.
data-chromeThe label of a product shown as texture.2.5%, and no read hold.
data-uiA mock screen that is the subject of the film. Its text is read as real UI.3%
data-texture="<reason>"Says why the text is texture.None

A mark alone is not enough. The checks skip aria-hidden and data-chrome text only when it is texture by measure. This means one of these is true:

  • The cap height is under 2% of the frame.
  • The same words appear 3 times or more on the page.
  • data-texture holds a reason of 12 characters or more.

Any other marked text is checked as copy, and the draft check says how many text nodes this affects. Remove the mark, or add data-texture="why".

Limits

  • A DESIGN.md line type-scale: 4% or ui-scale: 2.5% replaces the copy floor or the data-ui floor for that film.
  • A text can be part of a canvas or a three.js scene. The checks read only DOM text.

On this page