react-typesetting

This page is a demonstration of react-typesetting, a collection of React components for projects that emphasize text-heavy design.

<TightenText>

The TightenText component is intended to give short runs of text (like titles, labels, etc.) some “give” before wrapping. This is useful when you want to prioritize having fewer lines of text over having completely rigid visual tightness.

When a line is just slightly too long for the available space, the text will be set tighter by a barely perceptible amount to avoid wrapping. By default, adjustments are made to word spacing, letter spacing, and font size (preferentially in that order).

Try dragging to adjust the available space for this line from a cocktail recipe:

Drag to resize!
Islay single malt Scotch whisky

Notice that the text resists both wrapping (when a new line would be formed) and overflowing (when the words can’t be broken any more) – up to a certain point.

<PreventWidows>

Although the terminology varies, “widows” often refer to very short lines of text at the end of paragraphs. This tends to be undesirable during typesetting, as it gives the appearance of too much whitespace between the paragraph and any elements that follow, and can be distracting. It is generally preferable to find a way to either remove the extra line (a la TightenText) or make it longer. If possible, you can even just opt to reword your writing.

Many HTML typesetting helpers implement this in a naïve way – for example, by always joining the last word with a non-breaking space. This gives poor results, since it does not account for how long the last line actually is. Try the naïve approach to see how it fails to achieve the desired wrapping:

Drag to resize!
The Long Goodbye

The PreventWidows component instead works by actually measuring the widths of lines, and can thus support many different ways to specify the desired minimum width – including percentages, pixels, and ems. The default minimum is 15% of the available width.

In this demo, a custom nbspChar element is supplied that highlights the inserted spaces for demonstration purposes:

Drag to resize!
Call me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I…

The current strategy works especially well with justified text, since there is no rag on the preceding line to worry about:

Drag to resize!

One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked.

<Justify>

Sometimes you want to render justified text, but due to changing element sizes in a responsive design, it could make things worse. Justified text tends to look bad in narrow columns of text, because it forces very large spaces between the words. For example:

Drag to resize!

There was no possibility of taking a walk that day. We had been wandering, indeed, in the leafless shrubbery an hour in the morning; but since dinner (Mrs. Reed, when there was no company, dined early) the cold winter wind had brought with it clouds so sombre, and a rain so penetrating, that further out-door exercise was now out of the question.

The Justify component solves this by conditionally setting text as justified only when there is enough room, and otherwise the text will inherit its alignment as normal. Here is the same paragraph as above, but using conditional justification. Try making it wider:

Drag to resize!

There was no possibility of taking a walk that day. We had been wandering, indeed, in the leafless shrubbery an hour in the morning; but since dinner (Mrs. Reed, when there was no company, dined early) the cold winter wind had brought with it clouds so sombre, and a rain so penetrating, that further out-door exercise was now out of the question.

<FontObserver>

When creating pages with typographically important features, sometimes you’ll want to know when your custom fonts are done loading. Perhaps you’ve done some rendering calculations that are influenced by font metrics (like how wide a line of text is) and thus need to recompute them when your font is shown? The components above are great examples of this.

The FontObserver component offers an interface to this information. By supplying FontObserver.Provider a list of fonts to observe, it will use Font Face Observer to populate a React context provider with status information for each font. You can then use FontObserver anywhere in the subtree to get updates.

Below is a list of the fonts used on this page, rendered using data from FontObserver. The symbol rendered next to each font is based on the loaded and error properties that are populated for each font.

  • Courgette
  • Libre Baskerville • 400
  • Libre Baskerville • 400 • italic
  • Libre Baskerville • 700

Documentation

All options are documented in the README.