That empty □ box isn't a broken character — it's a missing glyph. Here's how I stopped patching tofu with SVGs and built a font that physically can't tofu.
You've seen it: a little empty rectangle where a symbol should be. Designers call it tofu. The text is fine — the font just doesn't contain a shape for that codepoint, so the browser draws a box and moves on.
It bit me on a tiny "★ wildcard" badge in an admin panel. Instead of a star, I got □ wildcard.
The one insight that explains every tofu box
A font-family stack is resolved per character. For each codepoint the browser walks your stack until a font has a glyph for it. If none do — tofu.
The trap is subtle: emoji fonts don't contain text dingbats.
★is U+2605 BLACK STAR — a text symbol.⭐is U+2B50 — an emoji.
My stack ended in Noto Color Emoji (self-hosted, so symbols render the same on every OS). Noto has the emoji star but not the text star — so the browser routed ★ to the emoji font, found nothing, and boxed it. I confirmed it with a 20-line glyph viewer:
DelaGothicOne-Regular: U+2605 PRESENT
NotoColorEmoji.v2: U+2605 MISSING
Fix #1: inline SVG (fine for one icon)
Swap the character for an inline <svg> star. Zero font dependency, renders everywhere. But you can't SVG every ★, →, ✓ across a dozen sites. It doesn't scale.
Fix #2: just add the glyph to the font
Here's the move almost no one reaches for: a font is editable. If Noto is missing ★, graft it in — borrowed from a font that has it (Dela Gothic One) — using fontTools. The only wrinkle is unit scaling: Dela is 1000 units/em, Noto is 1024.
scale = noto['head'].unitsPerEm / dela['head'].unitsPerEm # 1024/1000
pen = TTGlyphPen(None)
DecomposingRecordingPen(dela.getGlyphSet())[star].replay(
TransformPen(pen, (scale, 0, 0, scale, 0, 0))) # scaled outline
glyf.glyphs[name] = pen.glyph()
glyf.glyphOrder.append(name) # keep glyphs + order in sync
for t in noto['cmap'].tables:
if t.isUnicode():
t.cmap[0x2605] = name # U+2605 now resolves
noto.save('TrioEmojiStar.woff2')
The best part: the star lands in the glyf table with no COLR color layer, so it renders in currentColor — a clean, themeable black star — while all 1,485 real emoji keep their color. One font, every emoji plus the star, and it physically cannot tofu that codepoint.
The payoff
Tofu is never a mystery. It's a missing glyph — and a glyph is just data you can add.
Originally posted on trentontompkins.com. Grab the kit (both fonts + the glyph viewer + the font forge): never-tofu-font-kit.zip.