How to debug an icon font that isn't showing the right glyph
- Step 1Grab the font your app actually loads — Open DevTools → Network, reload, and download the `.woff2`/`.ttf` your page requested — not a copy from elsewhere. Bugs often come from a stale or wrong file being served.
- Step 2Preview it here — Drop the downloaded font. It's parsed and embedded as an `@font-face` (`font-display: block`); the grid renders every codepoint-bearing glyph with its `U+` caption.
- Step 3Find the codepoint from your CSS — Your CSS has `content: "\e042"`. Look for a cell captioned `U+E042` in the grid.
- Step 4Read the result — Glyph renders here = font is fine, fix your app. Cell shows a box = outline missing from the file. No cell = the font doesn't encode that codepoint.
- Step 5Check the weight/family if it's the wrong icon — If a different picture shows under your codepoint, you may be loading the wrong file (solid vs regular) or a different `font-weight`. Preview each candidate file and match the one that has your icon.
- Step 6Fix the root cause — Wrong codepoint → use the one the grid shows. Missing outline → re-subset. No encoding → re-add the glyph or point at the right font. Wrong file → fix your `@font-face src`.
Tofu / wrong-icon triage
Match what you see in your app against what the previewer shows for the same codepoint to localise the bug.
| Your app shows | Grid shows for that `U+` | Likely cause | Fix |
|---|---|---|---|
| Tofu box | No cell at that codepoint | Codepoint not encoded in the font | Use the codepoint the grid shows, or re-add the glyph |
| Empty square | Empty box at that codepoint | Outline stripped (over-subset) | Re-subset keeping the outline |
| Correct icon | Correct glyph renders | Font is fine — CSS / loading bug | Check @font-face src, font-family, weight |
| Wrong icon | Different glyph under that U+ | Wrong file or codepoint shift | Match file (solid/regular) and pin codepoints |
| Nothing then flash | Glyph renders fine | FOUT / font not loaded yet | Set font-display and preload the font |
Why font-display: block helps debugging
The previewer uses font-display: block, which changes what a missing glyph looks like versus a typical page setup.
| Setting | Missing-glyph behaviour | Diagnostic value |
|---|---|---|
block (this tool) | Shows the font's own fallback box, not a system letter | A box clearly means 'glyph not in this font' |
swap (common in apps) | May show a system-font character briefly | Can masquerade the bug as a wrong letter |
No @font-face loaded | System font renders your content text/codepoint | You'd see a literal char or box — different signal |
Cookbook
A repeatable triage from symptom to root cause. Codepoints are illustrative — substitute the value from your CSS.
Codepoint mismatch (the common one)
ExampleYour CSS uses \e042 but the grid has no U+E042 cell — your codepoint is wrong for this font.
CSS: .icon::before { content: "\e042"; }
Grid: no cell captioned U+E042
-> the font doesn't encode E042
-> find the icon visually, read its real caption (e.g. U+E88A)
-> change CSS to content: "\e88a"Outline stripped by a subset
ExampleThe cell exists but renders as a box here too — the file itself is missing the outline.
Grid: cell at U+E042 renders as [] -> outline gone, codepoint kept (over-subset) -> the font is the problem, not your CSS -> re-subset keeping that glyph's outline
Font is fine — it's your loading
ExampleThe glyph renders correctly here but not in the app. The font file is good; the bug is in how the app loads or styles it.
Grid: U+E042 renders the correct icon -> font file is fine Check in your app: - is @font-face src pointing at THIS file? - does font-family match exactly? - is font-weight correct (solid=900 vs regular=400)? - is the request 200, not 404/CORS-blocked?
Wrong icon = wrong file or weight
ExampleA different picture appears under your codepoint. You're likely loading the wrong split file or weight.
App: \f015 shows a brand glyph, not the house Preview fa-solid-900.woff2 -> U+F015 = house Preview fa-brands-400.woff2 -> U+F015 = a brand mark -> your @font-face src + weight point at brands, not solid
FOUT, not a missing glyph
ExampleThe icon flashes a fallback then appears. The glyph is present; the font just hadn't loaded yet.
Grid: U+E042 renders fine (glyph present) App: box flashes, then the icon appears -> Flash Of Unstyled Text while the font loads -> preload the font and set a sane font-display (see preload + font-display sibling tools)
Edge cases and what actually happens
Every row below was probed against the live API. Some documented requirements (alphabetical axis order, numerical tuple order) are not actually enforced in practice — useful to know if you've been blaming the wrong thing for a 400.
Glyph renders in the grid but is tofu in your app
Font is fine — app bugIf the previewer paints the glyph at the codepoint your CSS uses, the file is correct and the problem is elsewhere: a 404/CORS on the @font-face src, a mismatched font-family, or the wrong font-weight. Fix the loading, not the font.
Your codepoint has no cell in the grid
Codepoint not encodedThe most common tofu cause: your content: points at a codepoint the font doesn't encode. Find the icon visually, read its real U+ caption, and update the CSS. There's no cell because there's no cmap entry.
The cell renders as an empty box here too
Outline missing from the fileIf the previewer also shows a box at that codepoint, the outline was stripped (over-subset) while the cmap entry stayed. The font is the problem. Re-subset keeping the glyph with a font subsetter.
Wrong icon under the right codepoint
Wrong file or codepoint shiftA different picture under your codepoint means you're loading the wrong split file (solid vs regular vs brands) or a rebuild reassigned codepoints. Preview each candidate file and match the one whose grid shows your icon.
The glyph you want is ligature-only
Not addressable by codepointSome fonts (Material Symbols) reach a glyph only via ligature, with no direct codepoint — so it has no cell and content: can't target it. Use the ligature name in markup instead, or pick a codepoint-bearing alternative.
It rendered fine in the grid and your app — just delayed
FOUT, not a font bugIf the glyph appears after a flash, the font loaded late. The grid proves the glyph exists, so the file is healthy — the fix is preloading the font and setting a sensible font-display, not touching the font itself.
Composite icon renders wrong but the codepoint is present
Component outline missingA composite glyph stacks components that often have no codepoint of their own, so they don't appear as cells. If the composite looks broken while its codepoint cell exists, inspect the component outlines per glyph with the glyph inspector.
Uploaded a .ttc collection to debug
Unsupported font formatCollections aren't supported (only ttf/otf/woff/woff2). If your app extracts a face from a .ttc, debug that single extracted face here.
No file selected
Error — upload requiredRunning with no file throws 'Upload a font file.' Grab the exact font your page loads (via DevTools Network) and upload that one — debugging a different copy can hide the real bug.
Font over the tier size limit
Rejected — exceeds tier limitPer-job limits are 5 MB Free / 50 MB Pro / 1 GB Developer. If the debug font is a large uncompressed TTF, preview the served .woff2 instead — it's the file your users actually get anyway.
Frequently asked questions
My icon shows a tofu box — how do I find why?
Upload the exact font your page loads. If your codepoint has no cell, it isn't encoded (fix the codepoint). If the cell is an empty box, the outline is missing (re-subset). If it renders fine, the font is good and the bug is in your CSS or loading.
The glyph renders here but not in my app — now what?
The font file is fine. Check that your @font-face src points at this file, the font-family matches exactly, the font-weight is right (e.g. 900 for solid), and the font request isn't 404 or CORS-blocked.
Why does the previewer help more than DevTools?
It isolates the font from your CSS, loading, and bundler. A clean render here narrows the bug to your app; a box here proves the font itself is broken.
What does an empty box in the grid mean?
The codepoint is encoded but the outline is gone — typically an over-aggressive subset. The font is the problem; re-subset keeping that glyph with the font subsetter.
I'm seeing the wrong icon, not a box — why?
You're likely loading the wrong split file (solid vs regular vs brands) or a rebuild shifted codepoints. Preview each candidate and use the file whose grid shows your icon under that codepoint.
Could it be a ligature problem?
Yes. If the glyph is reachable only by ligature (common in Material Symbols), it has no codepoint and no cell, so content: can't target it. Use the ligature name in markup or pick a codepoint-addressable glyph.
The icon flashes then appears — is the font broken?
No, that's FOUT — the font loaded late. The grid confirms the glyph exists. Preload the font and set a sensible font-display; the file is healthy.
Why does this tool use font-display: block?
So a missing glyph shows the font's own fallback box rather than a system-font character. That makes 'glyph not in this font' an unambiguous signal while debugging.
Which font should I upload to debug?
The exact one your page loads — grab it from DevTools → Network. Debugging a different copy can mask a stale-file or wrong-file bug.
Does it support .woff2?
Yes — WOFF2 is Brotli-decompressed and WOFF zlib-decompressed in the browser; TTF and OTF read directly. TTC collections aren't supported.
Is my font uploaded to a server?
No. Everything runs client-side, so you can debug internal or licensed fonts safely.
Can it show me which format my file actually is?
It reads the format to decode it, but for a dedicated magic-byte report (TTF/OTF/WOFF/WOFF2/TTC) use the font format identifier.
Privacy first
Every JAD Font tool runs entirely in your browser using opentype.js and the wawoff2 WASM Brotli encoder. Your fonts never leave your device — verified by zero outbound network requests during processing.