Combining marks are encoded characters with their own Unicode properties, but their visible positions usually depend on glyph shaping and font layout. A mark can be present in the string and still look detached if the font lacks suitable anchors or the renderer splits a cluster across font runs.
The sequence of code points is not a drawing instruction
The text é contains LATIN SMALL LETTER E followed by COMBINING ACUTE ACCENT; U+00E9 contains the precomposed LATIN SMALL LETTER E WITH ACUTE. These are canonically equivalent under Unicode normalization, but they are different encoded sequences before normalization.
A shaper may use an existing precomposed glyph, decomposed glyphs with anchors or fallback methods. The fact that both render as a familiar accented letter does not establish whether the source contains one scalar or two. Preserve code-point annotations in bug reports.
Canonical combining class helps define ordering
Unicode canonical combining class supports a canonical ordering of many nonspacing marks. During normalization, marks with distinct nonzero combining classes can be reordered where the algorithm allows it, while other relationships stay constrained. This is about stable text representation, not automatically arranging visible accents on a canvas.
For example, combining marks can have different canonical combining classes, and their canonical order matters to NFC/NFD equality. A font may still place them poorly even after correct normalization because font anchoring and layout are separate requirements.
Base-to-mark positioning uses anchors
OpenType GPOS MarkToBase attachment associates a mark glyph's anchor with a base glyph's anchor. The shaping output may give the mark a near-zero advance plus an offset so the diacritic sits at the expected position. Merely drawing the mark after the base at the current pen coordinate will not reliably reproduce the intended placement.
A font's anchors are design data, and different fonts can use different positions while remaining valid. When visual alignment breaks, inspect glyph IDs, GPOS lookup application, offsets and selected font face before attempting CSS letter-spacing workarounds.
Mark-to-mark attachment handles stacked marks
In words with multiple combining diacritics, mark-to-mark positioning can attach one mark to another. This becomes important for scripts and orthographies that use stacked accents. A base font that supports one isolated accent may not provide all mark classes or anchors needed for longer sequences.
If the second accent overlaps the first, the problem can be a missing MarkToMark lookup or a run split, not necessarily illegal Unicode input. Test both isolated pairings and realistic words. The same scalar sequence can look different if the selected font faces have different anchoring capabilities.
Fallback font splits can destroy attachment context
Suppose the primary font has a base letter but no relevant combining mark. A platform might choose fallback to cover the sequence, split glyph runs or apply synthetic combining behavior. There is no universal guarantee that two unrelated fonts share compatible anchor geometry.
When a mark is detached, use diagnostic tools to check the fonts assigned to the whole grapheme cluster. For high-fidelity applications, avoid splitting a complex sequence between faces if a suitable single font supports its shaping. A CSS unicode-range split needs tests with decomposed text as well as precomposed samples.
Grapheme boundaries and shaping clusters serve different needs
UAX #29 extended grapheme cluster rules usually keep a combining mark with its base for default cursor movement. A shaping engine may merge or reorder glyph clusters according to its own documented rules. The segmentation boundary is a user-interface abstraction, while attachment and advance are font-level rendering decisions.
An editor that deletes only U+0065 and leaves U+0301 behind can produce an orphan accent. A renderer that draws correct clusters but positions the accent poorly has a different defect. Treat editing and glyph placement as distinct issues in verification.
Normalization cannot repair a broken GPOS table
NFC may compose certain sequences when a precomposed character exists, but does not guarantee every combination has a precomposed representation. NFD decomposes precomposed characters into canonical components where applicable. Neither operation adds missing anchors or corrects a flawed font layout table.
Normalize when the application's data equality or storage contract requires it, not as a blind graphics repair. Compare NFC and NFD inputs explicitly to isolate whether shaping treats canonically equivalent forms consistently for the target font and script.
Debug with glyph positions and code point vectors
Capture U+0065 U+0301, U+00E9 and cases with two combining marks. Log the original scalars, normalization form, actual font selected, shaped glyph IDs, advances and x/y offsets. Reproduce at multiple scales to distinguish placement errors from raster clipping.
If offsets and glyph IDs match but the top accent is cut off, investigate line boxes, clipping and rasterization rather than rewriting text. If offsets differ unexpectedly between equivalent sequences, isolate the font and shaping configuration. Always preserve the original corpus fixture.
Reproducible experiment with fully specified input
Preserve the exact Unicode sequence before running the example. For browser comparisons, record the destination application, browser build, font files if relevant, system locale and any optional editor transformations. The example tests representation-level facts; it does not on its own demonstrate that every browser or native application must produce the same visual output.
const composed = '\u00E9';
const decomposed = 'e\u0301';
console.log(composed.normalize('NFD') === decomposed); // true
console.log(decomposed.normalize('NFC') === composed); // true
console.log([...decomposed].map(c => 'U+' + c.codePointAt(0).toString(16)));
// Test both forms against the same font, font size and shaping features;
// record mark glyph x_offset, y_offset and advance.A reliable technical report separates the original input, the representation delivered to an API and the outcome visible to the user. When a copy/paste or rendering test fails, retain the raw specimen and compare successive representations so that display-only differences do not get mislabeled as encoding changes.
Evidence matrix for combining marks and GPOS
| Feature | Controlled specimen | Interpretation |
|---|---|---|
| NFD input | U+0065 U+0301 | two scalars, often one grapheme cluster |
| NFC input | U+00E9 | precomposed scalar; canonical equivalent |
| MarkToBase | GPOS attachment | mark anchored to base glyph |
| MarkToMark | GPOS attachment | stacked marks require suitable positioning |
| fallback split | different font faces | may interrupt anchor geometry |
The entries above serve distinct roles: some characterize Unicode text data, while others specify font selection, layout, security policy or clipboard representation. Do not convert an environment-specific observation into a claim that Unicode mandates identical visuals or editing behavior across every platform.
Validation protocol for real-world applications
- NFD input: Establish a controlled specimen for U+0065 U+0301, record the input at the scalar level, then compare its output in the intended editor or rendering environment. two scalars, often one grapheme cluster. Document the location and circumstances of any transformation instead of treating a screenshot as sufficient evidence.
- NFC input: Establish a controlled specimen for U+00E9, record the input at the scalar level, then compare its output in the intended editor or rendering environment. precomposed scalar; canonical equivalent. Document the location and circumstances of any transformation instead of treating a screenshot as sufficient evidence.
- MarkToBase: Establish a controlled specimen for GPOS attachment, record the input at the scalar level, then compare its output in the intended editor or rendering environment. mark anchored to base glyph. Document the location and circumstances of any transformation instead of treating a screenshot as sufficient evidence.
- MarkToMark: Establish a controlled specimen for GPOS attachment, record the input at the scalar level, then compare its output in the intended editor or rendering environment. stacked marks require suitable positioning. Document the location and circumstances of any transformation instead of treating a screenshot as sufficient evidence.
- fallback split: Establish a controlled specimen for different font faces, record the input at the scalar level, then compare its output in the intended editor or rendering environment. may interrupt anchor geometry. Document the location and circumstances of any transformation instead of treating a screenshot as sufficient evidence.
Include adversarial and multilingual input, not only a short English word. Save code-point lists, serialized bytes when available, input method context, observed UI behavior and environment metadata. Repeat after browser, editor, operating-system or font updates; changes in renderer behavior do not imply that source strings were modified.
Frequent failure patterns and how to interpret them
- Confusing evidence about nfd input: A visual or API observation involving U+0065 U+0301 is not a comprehensive test of Unicode integrity. two scalars, often one grapheme cluster. Preserve the input, label the expected behavior and compare two independent stages before deciding whether a regression occurred.
- Confusing evidence about nfc input: A visual or API observation involving U+00E9 is not a comprehensive test of Unicode integrity. precomposed scalar; canonical equivalent. Preserve the input, label the expected behavior and compare two independent stages before deciding whether a regression occurred.
- Confusing evidence about marktobase: A visual or API observation involving GPOS attachment is not a comprehensive test of Unicode integrity. mark anchored to base glyph. Preserve the input, label the expected behavior and compare two independent stages before deciding whether a regression occurred.
- Confusing evidence about marktomark: A visual or API observation involving GPOS attachment is not a comprehensive test of Unicode integrity. stacked marks require suitable positioning. Preserve the input, label the expected behavior and compare two independent stages before deciding whether a regression occurred.
- Confusing evidence about fallback split: A visual or API observation involving different font faces is not a comprehensive test of Unicode integrity. may interrupt anchor geometry. Preserve the input, label the expected behavior and compare two independent stages before deciding whether a regression occurred.
In corrective workflows, preserve the user's original text until the responsible transformation has been identified. Avoid blanket removal of combining marks, variation selectors, joiners or directional controls: each can carry useful meaning in its intended context. If a product offers cleanup, make the behavior explicit and reversible.
Primary standards and implementation documentation
The references distinguish Unicode character properties and algorithms from browser APIs, CSS layout and particular implementation strategies. Normative conformance is narrower than identical visual output; document assumptions whenever a standard permits implementation-dependent behavior.
- Unicode Normalization UAX #15 — normative definitions or authoritative technical documentation relevant to combining marks and GPOS. Check the precise implementation conditions and distinguish platform behavior from the standard's guarantee.
- Unicode Text Segmentation UAX #29 — normative definitions or authoritative technical documentation relevant to combining marks and GPOS. Check the precise implementation conditions and distinguish platform behavior from the standard's guarantee.
- Unicode Character Database UAX #44 — normative definitions or authoritative technical documentation relevant to combining marks and GPOS. Check the precise implementation conditions and distinguish platform behavior from the standard's guarantee.
- OpenType GPOS Specification — normative definitions or authoritative technical documentation relevant to combining marks and GPOS. Check the precise implementation conditions and distinguish platform behavior from the standard's guarantee.
- HarfBuzz shaping manual — normative definitions or authoritative technical documentation relevant to combining marks and GPOS. Check the precise implementation conditions and distinguish platform behavior from the standard's guarantee.
Related technical references
The Fonts, Shaping & Text Rendering virtual silo groups practical investigations without adding category pages. The following already-published references cover adjacent layers needed to interpret this problem.
In a reproducible bug report, always preserve the exact text fixture and record the implementation version. The difference between an actual data transformation and a change of presentation determines both the correct fix and the risk of introducing further loss.