How to assign pua codepoints to a list of icon names
- Step 1List your icon names, one per line — Paste your icon names into the textarea, one name per line. Blank lines are trimmed and skipped, and leading/trailing whitespace on each name is stripped before assignment. Order matters — the first line becomes the first codepoint.
- Step 2Pick a start codepoint (or keep U+E000) — The **Start (hex)** field defaults to `E000`. You can type a bare hex value (`E000`, `F100`) or with a `U+` prefix (`U+F100`) — the tool strips the prefix. It must land in **U+E000–U+F8FF**; anything outside that range is rejected.
- Step 3Generate the mapping — Click Generate. Because this is a generative tool, there is no file to upload — the output is computed from your two inputs alone, in the browser.
- Step 4Read the metrics — The result panel reports `Icons assigned` (the count after blank lines are dropped) and `Range used` (e.g. `U+E000 – U+E027`). Cross-check the count against your expected icon total before shipping.
- Step 5Copy the CSS classes into your stylesheet — The output `.css` file contains one rule per icon — `.icon-home::before { content: "\e000"; }`. Paste these alongside your `@font-face` declaration that loads the actual icon font.
- Step 6Save the JSON manifest as your source of truth — Below the CSS rules, a comment block holds a JSON manifest with `start_hex`, `count`, and a `mappings` array (name, unicode, hex, cssClass, cssEscape, htmlEntity per icon). Extract it for your build, your docs, or your font-builder config.
The two inputs
Everything this tool accepts. There is no file upload and no other option — it is a pure text-to-codepoint mapper.
| Input | Type | Default | Notes |
|---|---|---|---|
iconNames | Textarea, newline-separated | (required) | One name per line. Split on newlines, each line trimmed, blank lines dropped. Empty input throws Paste at least one icon name. |
puaStartHex | Hex string | E000 | A U+/u+ prefix is stripped. Parsed as base-16. Must satisfy 0xE000 ≤ start ≤ 0xF8FF or it throws a range error. |
What each icon produces
For one input line, here is every field the tool derives. Example: the name home at start U+E000.
| Output field | Value for `home` @ U+E000 | How it is built |
|---|---|---|
unicode | 57344 | Integer codepoint = start + line index |
hex | U+E000 | Codepoint as uppercase hex, zero-padded to 4 digits, prefixed U+ |
cssClass | .icon-home | .icon- + name with every char outside [a-z0-9-] replaced by -, then lowercased |
cssEscape | \e000 | Backslash + lowercase hex (used in CSS content) |
htmlEntity |  | &#x + uppercase hex + ; |
PUA capacity at a glance
The tool assigns only inside the Basic Multilingual Plane PUA. The two Supplementary PUA blocks are referenced in the out-of-space error message as advice but are not assigned by this tool.
| Block | Range | Codepoints | Assigned by this tool? |
|---|---|---|---|
| BMP PUA | U+E000 – U+F8FF | 6,400 | Yes — the only block used |
| Supplementary PUA-A | U+F0000 – U+FFFFD | 65,534 | No — mentioned in error text only |
| Supplementary PUA-B | U+100000 – U+10FFFD | 65,534 | No — mentioned in error text only |
Cookbook
Real paste-in / paste-out examples. Output shown is the exact shape the tool returns; only the icon names change per scenario.
Four icons from the default start
ExampleThe canonical case: four names, default start U+E000. The CSS uses lowercase escapes; the manifest mirrors every field.
Input names (one per line):
home
user
search
settings
Start: E000
Output CSS (excerpt):
.icon-home::before { content: "\e000"; }
.icon-user::before { content: "\e001"; }
.icon-search::before { content: "\e002"; }
.icon-settings::before { content: "\e003"; }
Metrics:
Icons assigned: 4
Range used: U+E000 – U+E003Custom start at U+F100
ExamplePick any start inside the PUA. Pasting U+F100 or F100 both work — the prefix is stripped before parsing.
Input:
home
user
Start: F100
Output CSS:
.icon-home::before { content: "\f100"; }
.icon-user::before { content: "\f101"; }
Metrics:
Range used: U+F100 – U+F101Names with spaces and capitals get slugified
ExampleThe CSS class lowercases and replaces every character outside [a-z0-9-] with a hyphen. The original name is preserved in the manifest's name field — only the class is transformed.
Input:
Arrow Left
User_Profile
check.circle
Output CSS:
.icon-arrow-left::before { content: "\e000"; }
.icon-user-profile::before { content: "\e001"; }
.icon-check-circle::before { content: "\e002"; }
(manifest keeps name: "Arrow Left", "User_Profile", "check.circle")Reading the JSON manifest from the output
ExampleThe .css file ends with a comment block containing the full manifest. Parse it in your build for a single source of truth shared with your stylesheet.
/* JSON manifest:
{
"start_hex": "U+E000",
"count": 2,
"mappings": [
{ "name": "home", "unicode": 57344, "hex": "U+E000",
"cssClass": ".icon-home", "cssEscape": "\\e000",
"htmlEntity": "" },
{ "name": "user", "unicode": 57345, "hex": "U+E001",
"cssClass": ".icon-user", "cssEscape": "\\e001",
"htmlEntity": "" }
]
}
*/Using the HTML entity instead of a CSS class
ExampleWhen you want an inline icon without a class, paste the htmlEntity straight into markup. It uses uppercase hex.
Manifest field for 'star' @ U+E004: htmlEntity: "" Markup: <span class="icon-font"></span> (the .icon-font element must already load your icon @font-face)
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.
Empty icon-names field
Error — rejectedIf the textarea is empty (or only whitespace) the tool throws Paste at least one icon name. before doing anything. There is no default list — names are required.
Start below U+E000 or above U+F8FF
Error — invalid rangeA start like D000 or FA00 throws PUA start must be a hex codepoint in the U+E000–U+F8FF range. The tool refuses to assign outside the BMP Private Use Area so you never collide with assigned Unicode.
Non-hex start string
Error — invalid rangeA start that isn't valid hex (e.g. GHIJ) parses to NaN, fails the Number.isFinite check, and triggers the same range error. Use plain hex digits, optionally with a U+ prefix.
More icons than fit before U+F8FF
Error — out of spaceIf your list plus the start would pass U+F8FF, the tool stops at the overflow point with Ran out of PUA space at U+... (PUA ends at U+F8FF). Reduce icon count or split across BMP and SPUA-A. Lower the start or split the list — the tool itself only assigns within the BMP PUA.
Blank lines between names
Handled — skippedEmpty lines are filtered out before assignment, so a stray blank line in the middle of your list does not consume a codepoint or create a gap. The count reflects only non-empty names.
Leading/trailing spaces on a name
Handled — trimmedEach line is trimmed, so home becomes home. The trimmed name is what gets slugified into the CSS class and stored in the manifest.
Two names slugify to the same class
Silent — no dedupArrow Left and arrow-left both produce .icon-arrow-left, but each still gets its own unique codepoint. The tool does not detect or merge duplicate class names — later CSS rules with the same selector would override earlier ones in the cascade. Rename to keep classes unique.
You re-run after inserting a name in the middle
Caution — renumbersAssignment is positional from the start every time — there is no memory of a previous run. Inserting a name mid-list shifts every codepoint after it. To keep an existing mapping stable, append new names to the end of the list, never reorder. See the migration spoke for the stable-mapping workflow.
Name containing only punctuation
Handled — hyphen classA name like ++ slugifies to .icon--- (each non-alphanumeric becomes a hyphen). It is still assigned a codepoint, but the class is barely usable — give punctuation-only glyphs a readable name.
Codepoint as a decimal integer in the manifest
Expected — by designThe manifest's unicode field is the decimal codepoint (e.g. 57344), while hex is U+E000. If your build expects hex, read hex or cssEscape, not unicode.
Frequently asked questions
Does this build an actual icon font file?
No. This tool only maps names to codepoints and emits CSS plus a JSON manifest. It does not produce a TTF/WOFF/WOFF2 binary and does not embed any glyph outlines — you bring those to your font builder. To inspect or audit an existing font's glyphs, use glyph-inspector.
Do I upload my icon font here?
No upload. It is a generative tool that works from two text inputs — your icon names and a start hex. Nothing is sent to a server; the mapping is computed in your browser.
What is the Private Use Area?
Three Unicode blocks reserved for private agreements between a font and an application, with no standard meaning. This tool assigns only in the BMP PUA, U+E000–U+F8FF — 6,400 codepoints, ample for almost any icon set.
Why does the CSS escape use lowercase but the HTML entity uses uppercase?
That is how the tool builds them: cssEscape is a backslash plus lowercase hex (\e000), and htmlEntity is &#x plus uppercase hex (). Both reference the same codepoint — CSS and HTML are case-insensitive for hex here, so both work.
How are the CSS class names generated?
.icon- followed by your name with every character outside [a-z0-9-] replaced by a hyphen, then lowercased. So Arrow Left becomes .icon-arrow-left. The original name is preserved in the manifest.
Can I start somewhere other than U+E000?
Yes — type any hex value inside U+E000–U+F8FF in the Start field, with or without a U+ prefix. Common when you want to reserve a low band for a core set and start a second set higher up.
What happens if I list more icons than fit?
The tool stops and throws an out-of-space error naming the codepoint where it overflowed (the PUA ends at U+F8FF). It does not wrap or spill into the Supplementary PUA — reduce the count or lower the start.
Are duplicate names removed?
No. Every line gets its own codepoint, even if two names slugify to the same CSS class. Deduplicate your list before pasting if you want unique classes.
Is the output JSON or CSS?
Both, in one file. The .css file holds CSS ::before rules, and a trailing comment block contains the full JSON manifest. Read whichever your pipeline needs.
Does it remember my last mapping so codepoints stay stable?
No — each run numbers from the start independently. To keep an existing mapping stable, append new icons to the end of your list. The stable-mapping migration spoke walks through that workflow.
How many icons can the BMP PUA hold?
6,400 (U+E000 through U+F8FF). If you somehow need more, the error message suggests splitting across BMP and Supplementary PUA-A, but this tool itself only assigns within the BMP block.
How do I check which characters an existing font actually covers?
Use character-coverage-map to see covered ranges, or glyph-inspector to browse individual glyphs and their codepoints. To assemble a list of codepoints to keep for subsetting, see character-whitelist-builder.
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.