[mediaqueries-5] Add a prefers-lang media feature to expose user language preference
Nobody has claimed this yet.
- 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:
prefers-color-schemewent through this debate (#4162) and shipped. Language preference is not meaningfully more sensitive.- The
Accept-Languageheader is sent on every HTTP request. Servers already see this passively. CSS parity does not expand the attack surface for server operators. - 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.
- Browsers could expose a coarsened value (primary subtag only) rather than the full
Accept-Languagelist, 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-schemeas HTTP Client Hint, fingerprinting debate, shipped in Chrome asSec-CH-Prefers-Color-Scheme - #6915 —
:lang()for documents without content language Sec-CH-LangClient Hint — proposed but not widely adopted; no CSS equivalent-webkit-locale— internal Blink/WebKit property mappinglangattribute 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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