CSS-First UI Patterns · Page structure · 13

Language Switcher with hreflang

The best language switcher is a list of plain links. No script that guesses the visitor's language, no automatic redirect — just links that people and search engines can follow, connected with hreflang. Plus what changes when one of your languages is Chinese.

JavaScript
0 KB
Built with
<details>, hreflang, lang
Browsers
All current browsers (Chrome, Edge, Firefox, Safari)
Updated
How should a language switcher work for SEO?

Give every language its own URL and link them with normal <a> links — written in their own language, marked with lang and hreflang. Connect the versions with <link rel="alternate" hreflang="…"> in the <head>. Don't redirect visitors automatically by IP address or browser language: search engine crawlers get redirected too, and may never see your other versions.

Live demo

The real language switch between Jademond's English and Chinese websites. Click it, or Tab to it and press Enter. Each language is shown in its own script — someone who reads only Chinese finds “简体中文”, not “Chinese”.

Live demo 0 KB JavaScript Click · Enter

How the language switcher works

  1. Plain links, nothing else

    Each language is an <a href> to its own URL. Crawlers follow it, visitors can open it in a new tab, and it works when scripts fail. A <select> that changes the page with JavaScript does none of that.

  2. A native dropdown

    <details> and <summary> open and close the list with mouse, touch and keyboard. With only two or three languages, you can skip the dropdown and show the links side by side.

  3. Languages in their own words

    “简体中文”, “Deutsch”, “日本語” — not “Chinese”, “German”, “Japanese”. A visitor who can't read the current page must still recognise their language.

  4. lang on each link

    lang="zh-CN" tells screen readers to pronounce “简体中文” as Chinese, and lets browsers pick the right font.

  5. hreflang on each link

    It says which language the target page is in. Search engines take the binding signal from the <link> tags in the <head> (below); on the link itself it is a helpful hint.

  6. No flags

    Flags stand for countries, not languages. Chinese is the language of mainland China, Taiwan, Hong Kong and Singapore — which flag would you pick? Text labels avoid the question.

Copy the HTML and CSS

Exactly the code running in the demo. Replace the two links with the URLs of the current page in each language — not your home pages — so visitors land on the same content in their language.

language-switcher.html
<nav class="ui-lang" aria-label="Language">
  <details class="ui-lang__menu">
    <summary>
      <span class="ui-lang__icon" aria-hidden="true">文A</span>
      <span lang="en">English</span>
    </summary>
    <ul>
      <li><a href="https://www.jademond.com/" hreflang="en" lang="en" aria-current="true">English</a></li>
      <li><a href="https://www.jademond.cn/" hreflang="zh-CN" lang="zh-CN">简体中文</a></li>
    </ul>
  </details>
</nav>
language-switcher.css
/* Language switcher — no JavaScript.
   Plain links to each language version, in a native <details>
   dropdown. Each language is written in its own language,
   and marked with lang and hreflang. */
.ui-lang {
  --ui-bg: #ffffff;
  --ui-text: #1b1f3b;
  --ui-accent: #4f46e5;
  --ui-hover: #eef0ff;
  position: relative;
  display: inline-block;
  font: 500 0.9375rem/1.4 system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--ui-text);
}
.ui-lang summary {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.9rem;
  border-radius: 8px;
  background: var(--ui-bg);
  cursor: pointer;
  list-style: none;
}
.ui-lang summary::-webkit-details-marker {
  display: none;
}
.ui-lang summary::after {
  content: "";
  width: 0.4rem;
  height: 0.4rem;
  margin: -0.2rem 0 0 0.15rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
}
.ui-lang summary:focus-visible,
.ui-lang a:focus-visible {
  outline: 2px solid var(--ui-accent);
  outline-offset: 2px;
}
.ui-lang__icon {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ui-accent);
}

/* The list of languages */
.ui-lang ul {
  position: absolute;
  top: calc(100% + 0.4rem);
  left: 0;
  z-index: 10;
  min-width: 12rem;
  margin: 0;
  padding: 0.35rem 0;
  list-style: none;
  border-radius: 10px;
  background: var(--ui-bg);
  box-shadow: 0 12px 32px rgb(15 18 40 / 0.2);
}
.ui-lang a {
  display: block;
  padding: 0.6rem 1rem;
  color: var(--ui-text);
  text-decoration: none;
}
.ui-lang a:hover {
  background: var(--ui-hover);
}
.ui-lang a[aria-current] {
  color: var(--ui-accent);
  font-weight: 700;
}

The hreflang tags for your <head>

These connect the language versions for search engines. Every version lists all versions, including itself. x-default names the page for everyone else. (Example URLs — this page has no translations, so it doesn't use these tags itself.)

hreflang-head.html
<!-- In the <head> of EVERY language version of the page — the same set each time -->
<link rel="alternate" hreflang="en" href="https://www.example.com/products/">
<link rel="alternate" hreflang="zh-CN" href="https://www.example.cn/chanpin/">
<link rel="alternate" hreflang="zh-TW" href="https://www.example.com/zh-tw/products/">
<link rel="alternate" hreflang="x-default" href="https://www.example.com/products/">

<!-- And the language of each page on its <html> element -->
<html lang="zh-CN">

Language versions and SEO — Google and Baidu

Don't redirect automatically. Sending visitors to a language version based on their IP address or browser language feels helpful, but crawlers are visitors too. Google's crawler mostly comes from the US and doesn't send a language preference; a site that redirects it to English may keep its other versions out of Google's index. If you want to help visitors, show a small note — “This page is also available in 简体中文” — rendered on the server, and let them choose.

One language per URL. A page that mixes two languages, or switches language with a script while the URL stays the same, gives search engines nothing clear to index. That is also why we rewrote this lab in English only — the earlier versions mixed English and Chinese on one page.

hreflang is a Google and Bing signal. Baidu doesn't document support for hreflang. For Baidu, the Chinese version has to stand on its own: Simplified Chinese content written for mainland readers, <html lang="zh-CN">, fast hosting for China — in our experience ideally a separate site, often on a .cn domain. The plain links between the versions still help crawlers find it.

Simplified and Traditional are different versions. Mainland China and Singapore read Simplified Chinese, Taiwan and Hong Kong read Traditional — with different vocabulary, not just different characters. Treat them as separate versions with their own hreflang: zh-CN, zh-TW, zh-HK.

Accessibility and browser support

SituationWithout JSDetails
KeyboardWorksEnter or Space opens the list, Tab moves through the languages.
Screen readersWorksA “Language” navigation; each language name is pronounced correctly thanks to lang.
CrawlersWorksNormal links in the HTML, followed by every search engine.
Close on click outsideNeeds JSA <details> stays open until it is clicked again. Use a popover instead if that matters — see the modal page.
Remember the choiceServerThe URL already remembers it: each language lives on its own address.

Questions about language switchers and hreflang

Should I redirect visitors to their language automatically?

No. Crawlers may be redirected too and miss your other versions. Show a suggestion instead and let visitors choose.

What hreflang code should I use for Chinese?

zh-CN for Simplified Chinese aimed at mainland China, zh-TW for Traditional Chinese in Taiwan, zh-HK for Hong Kong. Use plain zh only if one version serves all Chinese readers.

Does Baidu use hreflang?

Baidu doesn't document support for it. Make the Chinese version strong on its own — content, lang="zh-CN", hosting — and link to it with plain links.

Should I use flags in a language switcher?

Better not. Flags stand for countries, many languages are spoken in several countries, and some flags are politically sensitive. Write each language's name in that language.

Where should the language switcher go?

In the header, usually top right, where visitors look for it — and again in the footer. It should look the same on every page.

This FAQ is built without JavaScript — see the accordion pattern.

One brand, several Asian markets

Planning a Chinese version — or Korean and Japanese too?

We set up Chinese websites that rank on Baidu, with the right structure between language versions. For Korea and Japan we work with trusted partners in each market.

CSS-First UI Patterns are written and maintained by Jademond Digital, a Chinese digital marketing agency founded in Guangzhou in 2012. We build and audit websites for Baidu, Google and AI search — which is why we care what works without JavaScript. About us →