# Missing lang attribute on <html>

> A missing lang attribute stops screen readers picking the right voice and search engines detecting language. Add lang to your <html> element.

_Category: Web essentials · Detector `web-essentials` · Check `lang` · Severity: warning_

The `<html lang>` attribute tells screen readers which pronunciation rules and voice to use, and tells search engines the content language for regional ranking. Without it, a screen reader may read English content with a French synthesizer, and translation tools guess. AI scaffolds that generate the app body rarely set the document language.

## Symptoms

- Screen readers use the wrong voice or pronunciation
- Browser “translate this page” offers to translate content that is already in the user’s language
- Lighthouse/axe report "html element does not have a [lang] attribute"

## How VibeCheck detects it

The `web-essentials` detector flags this live in the browser and reports it to the widget's Problems list — and to your coding agent over MCP.

- **Issue string:** `Missing lang attribute on <html>`
- **Threshold:** document.documentElement has no non-empty lang attribute

## Root causes

- The root `<html>` element was generated without a `lang` attribute
- A single-page app renders into `<body>` and never sets the document language

## The fix

Set a valid BCP-47 language tag on the root `<html>` element, e.g. `lang="en"` or `lang="en-US"`. If sections of the page are in another language, add `lang` on those elements too.

### Steps

1. Find where the root `<html>` element is defined
2. Add `lang="en"` (or your primary locale)
3. For multilingual pages, tag individual sections with their own `lang`

```html
<html lang="en">
```

## Framework-specific fixes

### React

Vite/CRA apps set it directly on the static `index.html` `<html>` element.

_index.html_

```html
<!doctype html>
<html lang="en">
```

### Next.js

In the App Router you own the `<html>` tag in the root layout — set `lang` there.

_app/layout.tsx_

```tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}
```

[Next.js docs](https://nextjs.org/docs/app/api-reference/file-conventions/layout)

### Vue

Set `lang` on the `<html>` element in `index.html`. For Nuxt, configure it via `app.head.htmlAttrs.lang`.

_index.html_

```html
<html lang="en">
```

### Svelte

SvelteKit sets it in `app.html` on the `<html>` tag. For per-request locales, use the `lang` placeholder and set it in a hook.

_src/app.html_

```html
<html lang="en">
```

## FAQ

### What value should `lang` be?

A BCP-47 tag: "en" for English, "en-US" for US English, "de", "pt-BR", etc. Use the most specific tag that is accurate for your content.

### Do I need `lang` on elements other than <html>?

Only if part of the page is in a different language. Then add `lang` on that element so assistive tech switches pronunciation just for that region.

## Related problems

- [Missing viewport meta tag](https://vibecheck.wcgw.fun/fix/missing-viewport-meta.md) — Web essentials
- [Missing charset declaration](https://vibecheck.wcgw.fun/fix/missing-charset.md) — Web essentials
- [Images missing alt text](https://vibecheck.wcgw.fun/fix/missing-image-alt-text.md) — Search visibility

---

Fix guide from VibeCheck — https://vibecheck.wcgw.fun/fix/missing-lang-attribute. Full site index for LLMs: https://vibecheck.wcgw.fun/llms.txt
