bouffont

is a small JavaScript library that grows letters from their bones. Give it a word and any font, and it swells, packs, blocks and folds the letters into one coherent hand as clean(ish) SVG.

One hand, any font

The font, , serves as skeleton. Each glyph is thinned down to its centre lines; serifs, stroke contrast and terminals are thrown away. The style is a combination of the font's anatomy and the algorithm.

Grown, not drawn

From there, the growth strategies take over: swell the letters, pack them with circles, grow them step by step until they lock into each other, cut their corners, snap their edges to 45°, or let them wrinkle like coral and freeze. Where two letters meet they can overlap, or repel each other into a shared seam.

Where a letter's swell meets itself across a gap, inner lines keep it readable.

Presets

Each preset is just a recipe of strategies; each name below is written in its own. The other titles on this page follow the playground's settings: change them and every title regrows.

Keep growing

After the letters meet, they can keep going. The swollen presets keep growing outward while their contacts stay put; the other presets run more generations of their own growth: another block swell, another round of wrinkles, another layer of frost.

Effects

Effects draw on the finished letters without changing them: a shine where the light hits, a shade on the far side, depth behind them, an inline along every edge, a band around the whole piece.

Use it

npm install bouffont
import { bouffont, loadFont } from 'bouffont';

const font = await loadFont('/fonts/iosevka.woff'); // any TTF, OTF or WOFF

const piece = bouffont({
  text: 'bouffont',
  font,
  seed: 'puff',
  preset: 'throwup',
});

document.body.innerHTML = piece.svg; // piece.letters holds the geometry

Every length is measured in stems, the pen's thickness, so the same settings behave alike on any font and at any size. Presets merge under your own options: change the outer shape with envelope, let letters repel, stand them on a line with align, write several lines with lineHeight, or pass your own strategies. The playground writes this code for you.

Every part is yours

piece.dom() hands back the SVG element and a reference to every fill, outline and inner line, for the whole piece and for each letter. Style them, animate them, react to them.

const { svg, letters } = piece.dom();
document.body.append(svg);

letters.forEach(({ group, fill, lines }, i) => {
  fill.style.animationDelay = `${i * 140}ms`; // a wave of ink
  group.addEventListener('pointerenter', () => group.classList.toggle('inked'));
});

Credits

Made by David Aerne; the source is on GitHub. Titles on this page are grown by bouffont from Merriweather; the text is set in Iosevka. Simulations after nshelton's growth experiments; measuring fonts from their glyphs after The Anatomy of a Thousand Typefaces.

Settings ▥
Text
Growth
skeletonrepelknit gaps
Lines
gap linesinner lines
Effects
Timeline

Playground

code: how to use it
editable, the piece follows