AccessibilityApril 29, 20268 min read

Document Title: One Element, Five Surfaces

A page's <title> isn't just the text in the browser tab. It's the first words a screen reader announces; the heading on a search-results card; the label that appears in bookmarks and history. Get it wrong and all of those break at once.

1. What is the document-title violation?

axe-core's document-title rule requires every HTML document to have a non-empty <title> in <head>. It's a direct mapping to WCAG 2.1 2.4.2 Page Titled (Level A).

When title is missing, empty, or identical across pages, users can't tell pages apart — especially when juggling tabs.

2. Why it matters

Title affects more surfaces than almost any other element:

  • Browser tab: Most users keep 10-20 tabs open. Title is what they see switching among them.
  • Screen reader: NVDA, JAWS, VoiceOver all announce title on page load — the very first thing the user learns.
  • Search results: Google derives the SERP heading mainly from title. CTR depends on it.
  • Bookmarks and history: Bookmark and history entries default to title. A meaningless title makes a page hard to find a week later.
  • Social shares: Without an OpenGraph title, share cards fall back to title.

One element, that many surfaces. A bad title sabotages SEO, UX, and accessibility at the same time.

3. When does it fire?

  1. No title element: No <title> in <head> at all. Common on programmatically generated pages.
  2. Empty title: <title></title> or whitespace-only.
  3. Meaningless default: <title>Document</title>, <title>Untitled</title>, or a CMS-supplied page id. axe-core can't catch text quality, but for accessibility these still count as missing.
  4. Same title on every page: Technically passes the rule but breaks WCAG 2.4.2's requirement that titles distinguish pages.
  5. SPA without title updates: When a single-page app changes routes without updating title, users don't hear that they've moved to a new page, and most screen readers stumble on the transition.

4. The fixes

4.1 Page-specific, descriptive title

A good title states the page's purpose in one line. The unique part comes first; the site name comes last, usually separated by a pipe.

Yanlış / WrongTells nothing about the page
<title>Site</title>
<title>Untitled</title>
<title>Home</title>
Doğru / RightContextual; ends with site name
<title>Accessible Button Names | Keysonar Blog</title>
<title>iPhone 15 Pro 256GB Blue — $1,299 | Keysonar</title>

4.2 Title format

A consistent template helps users orient instantly when switching tabs. Recommended: {Page Title} | {Site Name}. Putting the unique part first reads better for screen readers and improves SERP CTR.

  • Home: Site Name + short value prop
  • Category: Category Name | Site Name
  • Detail: Item Name | Category | Site Name
  • Error page: 404 — Page Not Found | Site Name

4.3 Next.js metadata API

In Next.js, generating title in each route's generateMetadata is the cleanest path for both dynamic content and multilingual sites.

Doğru / RightTitle for a dynamic blog page
// app/blog/[slug]/page.tsx
import type { Metadata } from "next";

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string }>;
}): Promise<Metadata> {
  const { slug } = await params;
  const post = await getPostBySlug(slug);

  return {
    title: `${post.title} | Keysonar Blog`,
    description: post.description,
  };
}
Doğru / RightTitle template at root layout
// app/layout.tsx
export const metadata: Metadata = {
  title: {
    template: "%s | Keysonar",
    default: "Keysonar — Web accessibility and SEO health",
  },
};

// Then a child page only writes the unique part:
// app/blog/[slug]/page.tsx
return { title: post.title }; // → "Accessible Button Names | Keysonar"

4.4 Updating title on SPA route changes

For client-side routes (Vue, React Router, Astro's client islands), title has to be updated by hand. Set document.title in a route hook — but after the page renders.

Doğru / RightTitle hook for React Router
function usePageTitle(title: string) {
  useEffect(() => {
    document.title = `${title} | Keysonar`;
  }, [title]);
}

function ProductPage() {
  const product = useProduct();
  usePageTitle(product?.name ?? "Loading");
  // ...
}

5. Title in multilingual sites

When a site has TR and EN versions, translate title too. An English "Home" on a Turkish page mismatches both the screen reader and the search engine's language classification.

Doğru / RightTitle from the i18n dictionary
export async function generateMetadata(): Promise<Metadata> {
  const locale = await getLocale();
  const t = await getTranslations(locale);
  return {
    title: t("blog.metaTitle"),
    description: t("blog.metaDesc"),
  };
}

The title's language must match <html lang="tr">. Mismatches will surface as separate violations under axe-core's html-lang-valid rule.

6. Cases that get missed

  • iframes: The document inside an iframe needs its own title; otherwise axe-core's frame-title rule fires.
  • Title length: Google truncates around 580px in SERPs. axe-core doesn't check length, but long titles hurt search appearance. Aim for 50-60 characters.
  • Dynamic glyphs: Emoji or unusual characters in title get announced as “star symbol” or skipped entirely by screen readers. Skip them unless they add meaning.
  • 404 / error pages: Often forgotten and left as “Untitled.” They need titles too.
  • Downloadable PDFs: The PDF's embedded title metadata also needs to be set; screen readers read PDFs the same way.

7. How to test

  1. Look at the browser tab: Does it tell you what page you're on at a glance?
  2. axe DevTools / Lighthouse: Both flag missing title immediately.
  3. Keysonar SEO Tools: Lists every page's title, surfaces missing, too-short, too-long, and duplicate titles. Essential for site-wide consistency.
  4. Screen-reader page load: With NVDA or VoiceOver running, open a new page and confirm the title is read clearly and accurately.

8. Quick checklist

  • Every page has a non-empty <title>.
  • Title is page-specific and reflects the content — not the same on every page.
  • Format is consistent: {Page Title} | {Site Name}.
  • SPA routes update title on navigation.
  • Title language matches the page's <html lang> value.
  • Title fits in roughly 50-60 characters and won't be truncated in SERPs.
  • iframes have their own title.
  • 404 and error pages carry meaningful titles.
  • Title is not 'Document', 'Untitled', or a CMS default.

9. References

  • WCAG 2.1 SC 2.4.2 — Page Titled — Level A
  • HTML Living Standard — The title element
  • Google Search Central — Title link best practices
  • Next.js — Metadata API

Catch these violations automatically across your site

Keysonar SEO Tools crawls every page, runs the full axe-core ruleset including button-name, and gives you the exact list of affected URLs.

Start free