Skip to content

Pages need a language

  • Rule: axe/html-has-lang
  • Checks: <html> element must have a lang attribute
  • WCAG: 3.1.1
  • Fix class: content: A fix needs authored text.
  • People who use a screen reader or a braille display, most of them blind.
  • People with cognitive, learning or attention disabilities.

The <html> element has no lang, or it is empty

Section titled “The <html> element has no lang, or it is empty”

Add lang with the language tag of the page’s main content, such as en, es or ja. Decide it from the language the content is written in.

<html lang="en">
<head>
<title>Plans - Acme</title>
</head>
<body>
<main>
<h1>Plans</h1>
</main>
</body>
</html>

Add lang with the same value. In a page served as HTML, xml:lang has no effect; keep it only beside a matching lang when the page is also served as XHTML.

Set lang in the HTML the server sends, from the language each page is in. If the page switches language in place, update lang with the content.

Hard-coding lang="en" in a template that serves pages in several languages

Section titled “Hard-coding lang="en" in a template that serves pages in several languages”

axe accepts it, but screen readers then read the other languages with English pronunciation. Set it from each page’s own language.

The part of the fix that differs in React, in its syntax. The rest of the guidance holds.

A client-rendered app has no lang on the <html> element in index.html

Section titled “A client-rendered app has no lang on the <html> element in index.html”

Add lang to <html> in index.html. The app renders inside <body>, so no component renders that element.

A root layout component renders the <html> element

Section titled “A root layout component renders the <html> element”

Set lang on the <html> it renders, from the page’s language.

function RootLayout({ locale, children }) {
return (
<html lang={locale}>
<body>{children}</body>
</html>
);
}

The app switches language without reloading the page

Section titled “The app switches language without reloading the page”

Set document.documentElement.lang in an effect that runs when the language changes.

function LanguageSync({ locale, children }) {
useEffect(() => {
document.documentElement.lang = locale;
}, [locale]);
return children;
}

Setting lang on the root <div> the app renders

Section titled “Setting lang on the root <div> the app renders”

axe still reports the page, because it checks <html>, and the <head>, with the page title, stays outside that <div>.

axe-core’s documentation of the rule

CORA’s fix guidance adapts content from accessibility-agents, under the MIT License: see its notice.