Em dashes in interface text
- Forbidden
- "Your plan — including every seat — renews monthly", "Free — forever", "Deleted — this cannot be undone"
- Instead
- A full stop, a comma, a colon or a new element. "Your plan renews monthly, including every seat." "Free forever." "Deleted. This cannot be undone."
What this rule looks like
Why this rule
Interface text is read in fragments, at a glance, in a space someone else's content has to fit too. An em dash is a pause the reader has to interpret: it stands in for a comma, a colon, a bracket or a full stop, and which one it is only becomes clear after reading past it. The punctuation that says exactly one thing is faster. It is also the clearest tell of machine-written copy. Generated text reaches for the em dash far more often than a person does, and readers have learned to notice. Copy that reads as generated is copy the reader trusts less, whatever it says. This is about interface strings: labels, buttons, headings, errors, empty states, help text, and the prose a page ships. Markdown counts where a framework renders it as a page, which is most of them (src/content, content/, MDX routes). A repository document does not: README.md, CHANGELOG.md, AGENTS.md and their kin are written for whoever works on the code, and so are your commit messages and this file. A verbatim quotation keeps its own punctuation. Text a page quotes from another source (a document, a spec, a person), marked as a quotation with <blockquote> or <q>, is that source's words, and so is a program's own output or code shown as it is, in <pre>, <code>, <samp> or <kbd>. Changing either to satisfy this rule would misquote it. The page's own copy around the quotation, and any heading or label it gives it, is still held to the rule. The en dash keeps its one job: ranges, where it is read as "to" (2–10 seats, Mon–Fri). That is not a pause, and it is not affected.
- Kind
- Rule
- Section
- UI writing
- Group
- Words
- Bucket
- mechanical
- Severity
- warning
- Detector
em-dash- Since
- v0.12.0