w3c / w3c/csswg-drafts

[mediaqueries-5] Add a prefers-lang media feature to expose user language preference

Open
#13,615 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

mediaqueries-5
Dominant language
Bikeshed
Stars
4.9k
Forks
816
PR merge metrics
PR metrics pending

Description

There is currently no CSS mechanism to match against the user's preferred language. :lang() matches the document's declared language (lang attribute, Content-Language header), not what the user's browser is configured to prefer.

On static hosting (GitHub Pages, S3, any CDN without edge compute), there is no server-side component to read Accept-Language and set <html lang> dynamically. The only option is JavaScript:

document.documentElement.lang = navigator.language.slice(0, 2);

This works but it forces a script dependency for something that should be declarative. Other user preferences already have media features — prefers-color-scheme, prefers-reduced-motion, prefers-contrast, prefers-reduced-transparency. Language is missing.

Use case

All 25 translations live in the DOM. CSS handles the rest — no JS, no server:

<span class="msg" lang="en">android will become a locked-down platform</span>
<span class="msg" lang="fr">android va devenir une plateforme fermée</span>
<span class="msg" lang="de">android wird eine geschlossene plattform</span>
.msg { display: none; }
:lang(en) > .banner .msg[lang="en"] { display: inline; }
:lang(fr) > .banner .msg[lang="fr"] { display: inline; }

This machinery works today. But :lang() only reads what the document declares, not what the user prefers. Bridging that gap requires JS or edge compute — neither should be necessary for what is a styling decision.

Proposal
@media (prefers-lang: fr) {
  .msg[lang="fr"] { display: inline; }
}

@media (prefers-lang: en) {
  .msg[lang="en"] { display: inline; }
}

Matching should follow BCP 47 prefix rules: (prefers-lang: en) matches en, en-US, en-GB, etc. This is consistent with how :lang() already handles subtag matching.

Privacy / fingerprinting

navigator.language is already exposed to JavaScript unconditionally — no permission, no opt-in. Any page running JS has this signal today. A CSS media feature does make it passive rather than active, which is a real tradeoff.

Counterpoints:

  1. prefers-color-scheme went through this debate (#4162) and shipped. Language preference is not meaningfully more sensitive.
  2. The Accept-Language header is sent on every HTTP request. Servers already see this passively. CSS parity does not expand the attack surface for server operators.
  3. Sites that need i18n already use JS to detect language. A media feature removes the JS tax without creating a new fingerprinting vector — the information is already available.
  4. Browsers could expose a coarsened value (primary subtag only) rather than the full Accept-Language list, limiting the entropy.
Prior art
  • prefers-color-scheme, prefers-reduced-motion, prefers-contrast — user preferences exposed via media features, shipped cross-browser
  • #4162 — prefers-color-scheme as HTTP Client Hint, fingerprinting debate, shipped in Chrome as Sec-CH-Prefers-Color-Scheme
  • #6915 — :lang() for documents without content language
  • Sec-CH-Lang Client Hint — proposed but not widely adopted; no CSS equivalent
  • -webkit-locale — internal Blink/WebKit property mapping lang attribute for font fallback, confirming engines already track locale internally
What this enables
  • CSS-only i18n on static sites — no JS, no edge compute, no server
  • Localized UI labels, banners, and content using only HTML + CSS
  • Progressive enhancement for sites that already have lang-tagged content in the DOM

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No repository file or test is identified in the issue. Start by reading the proposal and its cited CSSWG prior art, then determine where a new media feature would be specified and tested. Done means the feature’s matching, privacy, and BCP 47 behavior are resolved in the relevant specification and test plan.

Written by the indexing model from the issue text.

Assessment

Tech stack
css
Domain
frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.