Language and Page Titles
Set html lang, mark language changes, and keep unique descriptive document titles — SPA updates included.
- accessibility
- language-and
Screen readers choose pronunciation rules from language. Browser tabs and SR users rely on document titles to know where they are. Missing lang and generic titles (Home, App) are easy WCAG failures with outsized impact.
Docs: WCAG 3.1.1 Language of Page, 2.4.2 Page Titled, 3.1.2 Language of Parts.
Page language
<!doctype html>
<html lang="en">
<head>
<title>Billing settings · Acme</title>
</head>
…
</html>
Use a valid BCP 47 tag: en, en-US, fr, pt-BR, zh-Hans.
Wrong lang causes mispronunciation of the entire page.
Language of parts
When a phrase is in another language:
<p>The French motto is <span lang="fr">Liberté, égalité, fraternité</span>.</p>
Don’t mark proper nouns or loanwords already naturalized unless needed.
Unique, descriptive titles
| Bad | Better |
|---|---|
Home |
Dashboard · Acme |
Page |
Invoice #1842 · Acme |
| Same title every route | Per-route unique titles |
Pattern: {page} · {site} or {site} — {page} — pick one product convention.
SPA title updates
function setTitle(page: string) {
document.title = `${page} · Frontend Beauty`;
}
// on route change
setTitle('Accessibility tree');
Also move focus to main/h1 after navigation — focus management.
Frameworks
- Next.js:
metadata.title/generateMetadata - React Helmet / remix meta
- Astro:
<title>per page
Ensure client-side transitions still update title.
i18n apps
When user switches locale:
- Update
<html lang>. - Translate titles.
- Reload or remount content so AT picks up language.
document.documentElement.lang = locale; // 'es'
Footguns
lang="en"on a primarily Spanish site.- Titles only in the shell layout for all child routes.
- Flash of default title before hydration.
- Using brand code names users don’t recognize as the only title.
Interview out-loud answer
“I set html lang correctly, mark foreign phrases with lang, and give every route a unique descriptive title. SPAs update document.title on navigation and ideally move focus to the new page heading.”
Titles and browser history
Users scan the tab strip and history list. Duplicate titles (“Acme”) for every route make support harder. Include entity context when relevant:
document.title = product
? `${product.name} · Products · Acme`
: `Products · Acme`;
SEO overlap
Descriptive titles help search and a11y together. Avoid stuffing; keep human-readable. Soft SEO length guidance (~50–60 chars) matters less than uniqueness and clarity for AT users.
lang on widgets
Third-party embeds may inject another language. If you control the wrapper, set lang on the subtree. If not, document the gap for auditors.
i18n release checklist
Default html lang in the shell, locale switch updates lang, titles translated per route, mixed-language quotes marked, and one non-English SR smoke pass before major locale launches.
Subtitles and document structure
Some apps put the product name first (Acme · Settings); others put the page first (Settings · Acme). Pick one order and keep it. Screen reader users who open the window list benefit either way as long as the unique part is present and early enough to distinguish tabs.
Related on this site
- Heading hierarchy for a11y
- Focus management
- Skip links
- WCAG principles POUR
- Screen reader testing basics
Further reading
Related guides
- Accessible Combobox PatternBuild or evaluate comboboxes with APG keyboard behavior, aria-expanded/activedescendant, and filterable listbox pairing.
- Accessible Forms ErrorsLabel inputs, associate errors with fields, announce failures, and avoid placeholder-only forms that break accessibility.
- Accessible Menus PatternAPG menu and menubar keyboard model — arrow navigation, escape to close, aria-expanded, and when a disclosure is enough.
- Accessible Modals PatternsModal dialogs that work: focus trap, Escape, return focus, aria-modal, and why native dialog or APG patterns beat div soup.
- Accessible Names ComputationHow browsers compute accessible names from content, labels, aria-label, and labelledby — and how that powers Testing Library queries.