Intl.Segmenter: truncate names by whole graphemes

A five-character preview can split an emoji when it counts UTF-16 units. Segment the display text into graphemes before selecting the content to show.

Compare UTF-16 units, code points, and graphemes while keeping the original text. A separate preview appends an ellipsis only when whole segments were omitted.

Intl.Segmenter: truncate names by whole graphemes
Intl.Segmenter: truncate names by whole graphemes
Open the full example ↗

Use examples that expose the counting rule

Start with three supplied strings: Avery, Cafe followed by a combining acute accent, and the family emoji made from a man, woman, girl, and boy joined together. In source notation, the second is Cafe\u0301; the third is \u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}.

Sample UTF-16 units Code points Graphemes
Avery 5 5 5
Cafe plus combining acute 5 5 4
Joined family emoji 11 7 1

Use text.length for the first count, Array.from(text).length for the second, and the number of results from a grapheme segmenter for the third. The combining accent belongs with the preceding e in this sample. The seven code points belong to one joined emoji sequence.

These examples describe string boundaries. They do not promise a particular emoji drawing, font, or pixel width on every device. A single grapheme can still occupy more room than another.

Truncate the segments, not the source units

Create new Intl.Segmenter('en-US', { granularity: 'grapheme' }), segment the current text, and collect each segment's text. Take the requested number of those segments and join them. Append an ellipsis only if some segments were omitted.

For Avery with a preview limit of three, show Ave followed by an ellipsis. For the supplied accented word at four, show the entire word with no ellipsis. At a limit of one, the joined family emoji stays intact.

State that the ellipsis is an added display indicator outside the selected-content limit. A three-grapheme content limit with an added ellipsis does not produce a total three-grapheme string. That distinction matters when a preview later becomes a stored field with a strict limit.

Keep display limits separate from storage rules

Use this technique for a name badge preview or avatar label. Do not assume it matches a database's byte limit or a native input's maxlength behavior. Keep the original text available and show the truncated result as a separate preview.

Leave normalization out of the first version. The exercise should show the actual supplied string, including its combining sequence. If a later requirement introduces normalization, give it a separate control and explain how it changes the underlying data.

Handle an unavailable Intl.Segmenter explicitly. Show the original text and the two simpler counts, with the grapheme preview marked unavailable. Replacing grapheme segmentation with split on spaces or code points would silently change the rule the interface promised.

For a badge, choose the limit with an actual narrow layout rather than translating a database field size into a visual rule. Two names with equal grapheme counts can occupy different widths. Keep the full original in the editing control so a display preview never becomes an accidental data rewrite.

When reviewing the accented sample, compare the underlying sequence as well as the visible word. The e and combining accent form one segment here, even though they occupy two code points. That is why Array.from improves on string length for some emoji but still does not implement the promised grapheme rule.

For an empty string, all three counts are zero and the preview remains empty without an ellipsis. A limit of zero hides nonempty content and displays the added ellipsis; label that policy if you use it in a real component.

Try the worked example

Inspect Avery at limit 3 to get Ave…. Load the accented sample at 4 to preserve the complete word. Load the family at 1 to keep its joined sequence intact. Try a negative limit to clear the preview and show the valid range. The ellipsis is additional display text outside the content limit.

Grapheme count is not pixel width, database byte length, or proof of a particular font or emoji drawing.

Recreate this example

Build one complete self-contained HTML page for this task: inspect text counts and build a whole-grapheme display preview.

Use these exact original practice data and worked expectations: Avery has 5 UTF-16 units, 5 code points, and 5 graphemes. Cafe plus a combining acute accent has counts 5/5/4. The family emoji man-ZWJ-woman-ZWJ-girl-ZWJ-boy has counts 11/7/1. Avery at limit 3 gives Ave plus an ellipsis. Ellipsis is outside the content limit.

Implement the following useful local interactions: Provide editable text, integer limit 0–20, three sample buttons, Inspect. Use Intl.Segmenter en-US grapheme; no normalization. If unavailable display original and simple counts, mark grapheme preview unavailable. Show selected segments and preview. Preserve the supplied source text and distinguish an uncomputed state, a successful local result, and an invalid or incomplete input. Update output only from the current input snapshot. An input edit must retire stale feedback until the reader runs the relevant action again. Do not silently invent missing values or replace a failing case with a success.

Design the page as a compact source-and-result developer workbench with readable code, labeled inputs, and a separate explanation area. Put a compact task heading, actual sample data, the main result, and usable controls early enough to be useful on a narrow screen. Use readable text of at least 16px, generous paragraph spacing, strong contrast, native labels, accessible buttons, and visible keyboard focus. Stack long records at 360px and wrap code without page-level horizontal overflow.

Use type=button and explicit querySelector-based click handlers rather than relying on form submission. If Enter is useful, handle it only on the relevant input and ignore isComposing. Keep effects within this open page; no remote dependencies, network calls, persistence, fake downloads, or automated sending. Grapheme count is not pixel width, database byte length, or proof of a particular font or emoji drawing. Place worked explanations beside their data and identify teacher or synthetic examples clearly. Output only the complete HTML document, with inline styles and script and LF line endings.

Review the grapheme-count and truncation inspector in NOS

Use the inspector’s three counts when deciding the rule for your own name badge. Review the accented word and joined-family preview beside their original strings in NOS, and revise eligible static content-limit explanations in visual editing mode before choosing the badge limit.

Keep reading