お疲れ。最近、君が書いているCSSのコードレビューをしていて、ふと思ったんだよ。「あ、ここ、わざわざ冗長なクラス名つけてないか?」ってね。
例えば、日本語サイトと英語サイトで、微調整のために `.u-lang-en` みたいなユーティリティクラスをHTML側にわざわざバインドしている場面。あれ、見るたびに私の胃がキリキリするんだ。HTMLはコンテンツの構造を定義する場所であって、言語の切り替えごときにクラス名を汚染される筋合いはない。
そこで今回のテーマだ。`:lang()`擬似クラス。
これ、知ってるようで意外と現場で見落とされがちな隠し味なんだが、マスターするとマークアップが劇的に美しくなる。今日は、中級からワンランク上のシニアへステップアップしたい君に向けて、この `:lang()` の本質を叩き込んでやろう。
—
なぜ `:lang()` なのか?(クラス名依存からの脱却)
フロントエンドを数年やっていると、「英語圏のユーザーが見たときに、特定のフォントファミリーに変えたい」「日本語と英語でインラインの改行位置や文字間隔(letter-spacing)を微調整したい」という要件に必ずぶつかる。
そのとき、素人がやりがちなのがこれだ。
Hello, World.
こんにちは、世界。
CSS側で `.en-style` と `.ja-style` を定義する。おいおい、ちょっと待てと。それ、本当にHTML側の仕事か? ページの根底にある言語情報は、すでに `` タグや親要素の `lang=”en”` や `lang=”ja”` として存在しているはずだ。ブラウザがすでに理解しているそのセマンティクスを、なぜわざわざクラス名で二重管理しなければならないのか。
ここで `:lang()` の登場だ。HTMLを汚さず、CSSだけで美しく言語ごとに対処できる。
Hello, World.
こんにちは、世界。
これに対するCSSはこう書く。
/ 言語に応じたスタイルの振り分け /
.text {
font-family: sans-serif;
}
:lang(en) .text {
font-family: ‘Inter’, -apple-system, BlinkMacSystemFont, sans-serif;
letter-spacing: -0.01em; / 英語のカーニング調整 /
}
:lang(ja) .text {
font-family: ‘Hiragino Sans’, ‘Meiryo’, sans-serif;
letter-spacing: 0.05em; / 日本語の読みやすさを考慮したトラッキング /
}
どうだ? HTMLは極めてクリーンになり、スタイリングの関心事は完全にCSS側にカプセル化される。これがプロのアーキテクチャだ。
—
ブラウザの裏側で何が起きているか?(`:lang()` の強力な継承メカニズム)
ここで少し、ブラウザのエンジンが裏側でどうやってこのセレクタを解釈しているか、そのメカニズムの話をしておこう。単に「属性セレクタ `[lang=”en”]` と一緒でしょ?」と思ったら大間違いだ。
1. 属性セレクタ(`[lang|=”en”]` など)との決定的な違い
属性セレクタは、あくまで「その要素自身が持っている属性の値」を文字通りマッチングさせる。
一方で、`:lang()` 擬似クラスは、CSSの継承(Inheritance)の概念を理解している。
つまり、親要素に `lang=”ja”` が指定されていれば、その子孫要素には一切 `lang` 属性が書かれていなくても、`:lang(ja)` はしっかりとヒットする。ブラウザはDOMツリーを上方向にたどり、最も近い祖先から言語コンテキストを継承して判定しているんだ。
2. サブタグや方言への賢いフォールバック
さらに実務でアツいのが、`:lang(en)` は `en-US` や `en-GB` といったサブタグ(ロケール)を持つ要素にも自動的にマッチするという仕様だ。
Color or Colour?
/ lang=”en-US” であっても、このスタイルは完璧に適用される /
:lang(en) {
/ 英語圏向けの共通スタイル /
}
属性セレクタでこれをやろうとすると、`[lang^=”en”]` みたいなワイルドカードを使わなきゃいけなくて、コードが途端に泥臭くなる。`:lang()` は、言語コードのツリー構造(BCP 47仕様)をブラウザがネイティブに理解しているからこそ、こうした緩やかかつ正確なマッチングができるわけだ。
—
現場で即コピペして使える!実践的ユースケース
理屈はこれくらいにして、明日から現場で使える具体的なコードパターンをいくつか授けよう。
パターン1:引用符(Quotes)の言語別自動切り替え
多言語サイトで最も `:lang()` が真価を発揮するのが、`` タグ(インライン引用)のクォーテーションマークの制御だ。日本語、英語、フランス語などで、適切な引用符の形は異なる。これをCSS一発で制御できる。
/ 言語ごとのインライン引用符の定義 /
:lang(ja) q {
quotes: “「” “」” “『” “』”;
}
:lang(en) q {
quotes: ““” “”” “‘” “’”;
}
:lang(fr) q {
quotes: “« ” ” »” “‹ ” ” ›”;
}
/ 実際に適用する /
q::before {
content: open-quote;
}
q::after {
content: close-quote;
}
これ、CMSから出力される多言語記事などにおいて、エディタ側でクォーテーションの種類を気にさせる必要がなくなるため、運用の現場ですごく感謝されるテクニックだ。
パターン2:ハイフネーション(単語の自動ハイフン区切り)の制御
英語などのラテン文字圏では、テキストの端できれいに単語を折り返すためにハイフネーション(`-` を入れて改行する)が必須になるが、日本語でこれをやると大惨事になる(ランダムな位置で文字がハイフンで切れる)。
/ 日本語では絶対にハイフネーションさせないが、英語では有効にする /
:lang(ja) {
word-break: normal;
overflow-wrap: break-word;
}
:lang(en) {
hyphens: auto;
/ 英語の長文エリアなどで美しいレイアウトを担保 /
}
レスポンシブデザインにおいて、スマホなどの狭い画面で英語と日本語が混在するグローバルドキュメントを作る際、この切り分けが命綱になる。
—
最後に:シニアとして後輩に伝えたいこと
CSSを書くとき、私たちはついつい「どうやって見た目をコントロールするか(How)」ばかりに目が行きがちだ。`.is-active` だの `.en-text` だの、その場しのぎのクラス名を乱発してHTMLを肥大化させてしまう。
だが、本当に優れたフロントエンド・アーキテクチャとは、「HTMLが持つセマンティクス(意味構造)を最大限に信頼し、CSS側がそれに寄り添う形」で構築されているものだ。
言語情報という、HTMLが本来持っている尊いセマンティクスをブラウザに委ね、それをエレガントに拾い上げる `:lang()` 擬似クラス。今日の話を理解した君なら、もう無駄なクラス名を量産することはしないはずだ。
次のスプリントからは、スマートで美しい、誇れるコードを書いてくれ。期待しているよ。

コメント