Why Unicode has width-specific compatibility characters
East Asian computer systems historically used fixed-cell typography in which many CJK characters occupied a full cell while Latin letters and punctuation could occupy narrower cells. To interchange text from those legacy character sets without discarding width choices, Unicode encodes specific fullwidth and halfwidth compatibility forms. Their encoded identities differ from the ordinary characters to which they correspond, even when the distinction is mostly typographic.
For example, A is LATIN CAPITAL LETTER A (U+0041) while A is FULLWIDTH LATIN CAPITAL LETTER A (U+FF21). Likewise, the halfwidth Katakana カ (U+FF76) and regular Katakana カ (U+30AB) are different Unicode scalars with a compatibility relationship.
Unicode's East_Asian_Width property helps applications that need East Asian legacy encoding interoperability, character-cell approximations or width-sensitive text processing. The property does not prescribe actual glyph pixel width, and Unicode UAX #11 explicitly cautions that modern terminals need additional tailoring. Developers should distinguish a code point's compatibility width status, the chosen font's advance and the number of columns a particular terminal chooses to assign.
Fullwidth ASCII forms, halfwidth Katakana and small forms
The main Halfwidth and Fullwidth Forms block spans U+FF00..U+FFEF. Its fullwidth ASCII-compatible graphic characters run from U+FF01 FULLWIDTH EXCLAMATION MARK to U+FF5E FULLWIDTH TILDE. Most correspond exactly to ASCII U+0021..U+007E by adding 0xFEE0 to the code-point value. This relationship is valid only over the documented ASCII graphic range and does not apply to arbitrary Unicode punctuation or space.
The matching fullwidth space is U+3000 IDEOGRAPHIC SPACE, outside U+FF00; its NFKC decomposition maps to ordinary U+0020 SPACE. Halfwidth Japanese punctuation and Katakana forms occupy U+FF61..U+FF9F. The suffix U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK has a compatibility relationship to a combining dakuten rather than merely becoming an independent ordinary spacing glyph.
Unicode also has a Small Form Variants block U+FE50..U+FE6F with small punctuation and symbols historically used in East Asian layouts. The visually reduced SMALL COMMA (U+FE50) and SMALL COMMERCIAL AT (U+FE6B) are not new abstract punctuation meanings; they carry width/presentation distinctions for compatibility. Separately, vertical presentation forms in U+FE10..U+FE1F and U+FE30..U+FE4F support legacy orientation conventions. Modern layout may instead use semantic text plus CSS vertical-writing properties.
| Source | Unicode identity | NFKC result |
|---|---|---|
A | U+FF21 FULLWIDTH LATIN CAPITAL LETTER A | A U+0041 |
! | U+FF01 FULLWIDTH EXCLAMATION MARK | ! U+0021 |
~ | U+FF5E FULLWIDTH TILDE | ~ U+007E |
| Ideographic space | U+3000 | U+0020 SPACE |
カ | U+FF76 HALFWIDTH KATAKANA LETTER KA | カ U+30AB |
ガ | U+FF76 U+FF9E sequence | ガ U+30AC |
﹐ | U+FE50 SMALL COMMA | , U+002C |
﹫ | U+FE6B SMALL COMMERCIAL AT | @ U+0040 |
The six East_Asian_Width property values
Unicode Standard Annex #11 defines a property with six values that help determine width behavior under relevant contexts:
| Value | Short | Meaning |
|---|---|---|
| Fullwidth | F | Explicit fullwidth compatibility forms |
| Halfwidth | H | Explicit halfwidth compatibility forms |
| Wide | W | Implicitly wide characters, such as many East Asian ideographs |
| Narrow | Na | Implicitly narrow characters including many ordinary Latin forms |
| Ambiguous | A | May be wide or narrow depending on East Asian context and tailoring |
| Neutral | N | Not classified as East Asian wide/narrow for that purpose |
The property is not simply “wide if code point is in CJK blocks.” Many symbols and punctuation marks have ambiguous width. Fonts may use proportional layout. Unicode specifically recommends treating ambiguous-width characters as narrow by default where the relevant East Asian legacy context cannot be established.
Characters in the Small Form Variants block can have a UAX #11 width designation that does not intuitively match the English word “small” in their names. As a concrete example, U+FE50 SMALL COMMA has East_Asian_Width=Wide (W) in the property data. Its name and compatibility mapping describe a historical presentation form rather than a guarantee of a half-cell terminal advance.
NFKC width folding and its limitations
Unicode NFKC performs compatibility decomposition and canonical recomposition. It generally maps fullwidth ASCII variants back to ASCII, halfwidth Katakana to their ordinary Katakana counterparts and small punctuation to corresponding base forms. This process is not the same as simply changing the font width: the resulting string has different code points and may contain a different number of code points.
const input = "ABC123";
console.log(input.normalize("NFKC")); // "ABC123"
console.log("ガ".normalize("NFKC")); // "ガ"
console.log("\u3000".normalize("NFKC")); // " "
console.log("\uFE50".normalize("NFKC")); // ","
const original = "ガ"; // two code points
const normalized = original.normalize("NFKC");
console.log([...original].length); // 2
console.log([...normalized].length); // 1
Because NFKC can affect many other compatibility characters—including mathematical styled letters, superscripts and circled digits—it is too broad when your application intends only a width conversion. A width-specific converter should use explicitly defined mapping rules or a trusted library with documented semantics, possibly limited by code-point ranges and chosen locale. Keep the original text when appearance or mathematical meaning matters.
NFC alone does not ordinarily collapse width variants. Canonical equivalence and compatibility equivalence are distinct. If a database key is intended to ignore width, that choice must be implemented and documented explicitly rather than assumed from UTF-8 encoding.
Safe fullwidth conversion and normalization tests
The ASCII fullwidth formula is useful precisely because its domain is small and well-defined. Do not apply it to combining marks, CJK characters, supplementary mathematical alphabets or arbitrary punctuation. For spaces, handle U+0020 separately if a feature explicitly requests a fullwidth space.
function fullwidthAscii(text, widenSpace = false) {
return [...text].map(ch => {
const cp = ch.codePointAt(0);
if (cp >= 0x21 && cp <= 0x7E)
return String.fromCodePoint(cp + 0xFEE0);
if (widenSpace && cp === 0x20) return "\u3000";
return ch;
}).join("");
}
console.log(fullwidthAscii("Hi! 25"));
// "Hi! 25" (ASCII space stays ordinary)
console.log(fullwidthAscii("A B", true));
// "A B" (ideographic space inserted deliberately)
console.log(fullwidthAscii("ABC").normalize("NFKC"));
// "ABC"
A production converter should validate round trips for its supported subset and disclose that other symbols remain unchanged. Distinguish fullwidth ASCII mapping from halfwidth Japanese kana conversion; the latter involves sequences and combining voicing marks that require normalization/shaping awareness. A naive one-code-point-to-one-code-point substitution can fail to combine ガ correctly.
Users trying a Fancy Text tool with fullwidth Unicode characters should understand that these are encoded compatibility forms, not a universal way to force double-width rendering on all devices. The content can often be copied, but recipient fonts and platform input policies still affect how it appears.
Layout, terminal cells and vertical text
In traditional fixed-cell East Asian typography, an implicit wide character often occupies a whole em and a narrow character a half em. Terminal emulators frequently model this as two columns and one column. Unicode UAX #11 explicitly warns that the East_Asian_Width property alone is not a turnkey solution for modern terminal layout: grapheme clusters, emoji sequences, variation selectors, combining marks and font fallback complicate actual cell width.
For example, a combining accent has no independent advance in the usual sense, even if its property value might suggest a broad East Asian classification. A joined emoji can occupy two terminal cells, several cells, or a fallback sequence depending on terminal policy. Use a terminal-appropriate measured-width API and match its Unicode version when aligning tables; counting Unicode scalar values is insufficient.
Modern vertical writing systems have specialized CSS features such as writing-mode: vertical-rl and text-orientation, which operate on logical text and fonts. Encoding legacy vertical presentation forms merely to rotate punctuation can cause copy/paste and normalization problems when the output moves into ordinary horizontal text.
Copy-paste, search, usernames and legacy encodings
Compatibility forms can survive a plain-text copy because they are Unicode characters. But exact matching distinguishes A from A unless the application explicitly normalizes or collation rules treat them as equivalent. A user handle, filename or database unique key could therefore compare differently across systems with different width-folding policies.
Width compatibility matters in Japanese search, where legacy data may mix halfwidth and ordinary Katakana, and in East Asian content imported from spreadsheets or messaging systems. A search system may derive a width-folded index while preserving original presentation in the stored text. This is distinct from full-language collation, accent handling and confusable detection.
Some visual lookalikes have multiple encoding histories (for example, wave dash versus fullwidth tilde). Do not implement width mapping by visual appearance alone: use exact Unicode names, compatibility mappings and documented legacy conversion tables appropriate to the origin encoding. Faulty transcoding between Shift JIS-related encodings and Unicode can create subtle punctuation mismatches.
Security-related identifier profiles may restrict compatibility forms or apply NFKC. Applying normalization after access-control checks can introduce collisions; define the canonical comparison format and check for uniqueness using the same strategy everywhere.
Versioned tests and failure modes
| Test | Expected result |
|---|---|
U+0041 + 0xFEE0 | U+FF21 (fullwidth A) |
U+0021 + 0xFEE0 | U+FF01 (fullwidth !) |
U+0020 + 0xFEE0 | Do not apply formula; space uses U+3000 instead |
NFKC of U+FF21 | U+0041 |
NFKC of U+FF76 U+FF9E | U+30AC (ガ) |
NFKC of U+FE50 | U+002C comma |
NFC of U+FF21 | Remain U+FF21 |
| East_Asian_Width of U+FE50 | W, despite the SMALL name |
A robust QA suite should use versioned EastAsianWidth.txt, UnicodeData.txt and NormalizationTest.txt, plus actual terminal/app screenshots and copy/paste comparisons. The property test verifies data classification; visual tests verify specific renderers. Neither layer subsumes the other.
Unicode East Asian Width and normalization references
- Unicode Standard Annex #11 — East Asian Width, six property values and tailoring caveats.
- Unicode Standard Chapter 22 — Compatibility and width forms.
- Unicode Chart — Halfwidth and Fullwidth Forms.
- Unicode Chart — Small Form Variants.
- UAX #15 — Unicode Normalization Forms, compatibility decomposition and recomposition.
- EastAsianWidth.txt, Unicode property data.
- W3C CSS Writing Modes Level 4, vertical text layout.
Independent Unicode technical reference. Width categories do not guarantee a fixed number of terminal cells or specific glyph metrics.