Write specific, active copy
Buttons name their result; copy is active, second person, in numerals.
From web-design-guidelines (Web Interface Guidelines), Copy.
Name What the Button Does
Submit each dialog empty, then with sk_1.
Vague, passiveBad
ContinueSpecific, activeGood
Save API Key<h2>Add API Key</h2>
<p id="key-msg">This key has 4 characters; keys have 16 or more.</p>
<button type="submit">Save API Key</button>
Count in Numerals
Start a round in each pane; click the highest count.
Counts in wordsBad
Deployments This Week
eleven deploymentsCounts in numeralsGood
Deployments This Week
11 deploymentsWordsNo rounds yet
NumeralsNo rounds yet
const nf = new Intl.NumberFormat();
const count = (n, noun) => `${nf.format(n)} ${noun}${n === 1 ? "" : "s"}`;
count(11, "deployment");
.count { font-variant-numeric: tabular-nums; text-align: end; }
Check Your Own Copy
Type a label, or pick an example.
PreviewButton
Try
Checks
const MINOR = new Set(["a", "an", "the", "and", "but", "or", "nor", "for", "so", "yet",
"as", "at", "by", "in", "of", "on", "to", "up", "via", "per", "from", "with"]);
const ACRONYMS = { api: "API", cli: "CLI", url: "URL", id: "ID", ssh: "SSH", dns: "DNS" };
function titleCase(text) {
const words = text.trim().split(/\s+/);
return words.map((w, i) => {
const lower = w.toLowerCase();
if (ACRONYMS[lower]) return ACRONYMS[lower];
if (/[A-Z]/.test(w.slice(1))) return w;
if (i > 0 && i < words.length - 1 && MINOR.has(lower)) return lower;
return lower.replace(/^(\W*)(\w)/, (_, p, c) => p + c.toUpperCase());
}).join(" ");
}
titleCase("save api key and redeploy");
Why it matters, pros and cons
Why it matters
A label promises what happens next; “Continue” makes people reread.
Pros
- Fewer wrong clicks in dialogs.
- The label doubles as a stable test selector.
- Errors that name the fix unblock people.
Cons
- Specific labels run longer, especially once translated.
- Title Case is a house style; consistency matters more.
- Passive fits when the actor is unknown: “Card declined.”