よっしゃ、任せてくれ! $langPseudoClass$ の話、ガッツリ掘り下げて、現場で「なるほど!」って思ってもらえるような記事に仕上げてやろう。単なる仕様の羅列じゃなくて、俺たちが普段コード書いてて「あー、これどうなってんだっけ?」ってなるような、リアルな部分も踏まえて解説していくぜ。
—
$langPseudoClass$ を使いこなして、国際化対応をもっとスマートに!
フロントエンドエンジニア諸君、こんにちは! 今日は、CSSのちょっとニッチだけど、知っておくと「おお!」ってなる、`:lang()` 疑似クラスについて、じっくり語り合おうじゃないか。
「いやいや、`:lang()` なんて使ったことないし、そもそも何に使うの?」って思った君、大丈夫。俺も最初はそうだった。でも、これが意外と、いや、かなり強力な味方なんだ。特に、Webサイトを多言語展開する時とか、特定の言語圏のユーザーにだけ、ちょっとしたスタイル調整をしたい時なんかには、もう手放せない存在になる。
$:lang()$ って、一体全体どういうヤツなんだ?
$:lang()$ 疑似クラスは、その名の通り、要素の 言語 に基づいてスタイルを適用するためのものだ。具体的には、HTMLの `lang` 属性やXMLの `xml:lang` 属性の値と照合して、マッチした要素にCSSを適用する。
例えば、こんなHTMLがあったとする。
This is an English paragraph.
これは日本語の段落です。
This paragraph doesn’t have a language specified.
この時、$:lang(en)$ と書けば、`lang=”en”` が指定されている `
` 要素だけを選択できる。$:lang(ja)$ なら、`lang=”ja”` の `
` 要素だけ。シンプルだろ?
なんで $:lang()$ なんて使う必要があるんだ?
「へー、便利そうだけど、わざわざそんなことしなくても、クラス名とかで分けられるじゃん?」って思った君、鋭い。確かに、管理が煩雑になるまでは、クラス名で言語ごとにスタイルを分けることもできる。でも、$:lang()$ を使うことには、いくつかの大きなメリットがあるんだ。
1. HTMLの構造を壊さない:
言語情報は、本来 `` タグや、各要素の `lang` 属性で管理されるべきものだ。 $:lang()$ を使えば、CSS側でその言語情報を参照できるから、スタイル適用のためだけに不要なクラス名を付けたり、HTMLの構造を無理やり変更したりする必要がなくなる。これは、保守性やセマンティクスの観点から、非常に大きい。
2. 宣言的な国際化対応:
Webサイトが多言語対応する時、各言語で表示が崩れたり、読みにくかったりする部分が出てくるのは、よくある話だ。例えば、日本語の句読点と英語の句読点は見た目が違うし、フォントのウェイトや行間も、言語によって最適な値が異なる場合がある。$:lang()$ を使えば、「英語の時はこのフォントで、この行間。日本語の時はこっちのフォントで…」といった具合に、CSS側で宣言的に言語ごとのスタイルを定義できる。
3. 継承の力で、さらに強力に:
$:lang()$ は、親要素の `lang` 属性も考慮してくれる。つまり、`` タグに `lang=”ja”` が指定されていれば、その直下にある `lang` 属性が指定されていない要素でも、暗黙的に「日本語」として扱われる可能性があるんだ(※ただし、これはブラウザの実装や、より具体的な `lang` 指定があるかどうかにも依存する。基本的には明示的な指定がベスト)。
これは、サイト全体でデフォルトの言語を設定し、部分的に別の言語のコンテンツを挿入する、なんていうケースで特に役立つ。
ブラウザの裏側:$:lang()$ はどうやって動いてる?
さて、ここまで「$:lang()$ は便利だよ!」って言ってきたけど、ブラウザは一体どうやって「あ、この要素は英語だな」とか「これは日本語だな」って判断してるんだろう?
実は、ブラウザはHTMLパーサーがDOMツリーを構築する過程で、各要素の `lang` 属性(または `xml:lang`)を読み取って、要素に 言語情報 として紐づけているんだ。CSSエンジンは、このDOMツリー上の言語情報を元に、$:lang()$ セレクタが指定された要素と照合する。
例えば、ブラウザが `
` という要素を見つけたとすると、DOMツリー上ではこの `
` 要素に「この要素の言語は英語 (en) である」という情報が付与される。そして、CSSのセレクタマッチングの際に、`:lang(en)` という指定があれば、「お、この要素は指定された言語と一致するな!」と判断して、スタイルを適用するわけだ。
興味深いのは、`:lang()` は言語コードだけでなく、より具体的なサブコード(例: `en-US` や `ja-JP`)にもマッチできること。例えば、`:lang(en-US)` と指定すれば、`lang=”en-US”` の要素にのみ適用され、`:lang(en)` なら `lang=”en”` や `lang=”en-US”`、`lang=”en-GB”` など、`en` を含む全ての言語にマッチする。これは、階層的な言語指定に対応するためなんだ。
現場で使える! $:lang()$ の実践的なサンプルコード
理屈は分かったところで、やっぱり現場で使えるコードを見たいよな? ここからは、俺がよく使うパターンをいくつか紹介しよう。コピペして、自分のプロジェクトで試してみてくれ!
サンプル1: 言語ごとのフォント指定
多言語サイトで、言語によって最適なフォントや表示の仕方が違うのは、よくある課題だ。$:lang()$ を使えば、これをCSSだけでスマートに解決できる。
This is an English paragraph. We use a different font for English to improve readability.
これは日本語の段落です。日本語は読みやすいように、専用のフォントを指定しています。
This paragraph has no language attribute. It will inherit the default language (ja) from the html tag.
/ styles.css /
/ デフォルトのフォント設定(ここでは日本語を想定) /
body {
font-family: ‘游ゴシック’, ‘Yu Gothic’, ‘メイリオ’, Meiryo, sans-serif;
line-height: 1.6;
}
/ 英語の段落に対するスタイル /
p:lang(en) {
font-family: ‘Helvetica Neue’, Helvetica, Arial, sans-serif; / 英語圏で一般的なフォント /
font-weight: 300; / 少し細めのウェイトで洗練された印象に /
color: #333; / 英語コンテンツは少し濃いめのグレーに /
margin-top: 1em; / 他の段落との間隔を調整 /
}
/ 日本語の段落に対するスタイル(明示的に指定) /
p:lang(ja) {
font-family: ‘游ゴシック’, ‘Yu Gothic’, ‘メイリオ’, Meiryo, sans-serif; / 日本語用のフォント /
font-weight: normal; / 標準的なウェイト /
color: #555; / 日本語コンテンツは少し薄めのグレーに /
margin-top: 1em;
}
/ 言語属性が指定されていない、または継承される要素へのスタイル(必要に応じて) /
/ この例では、htmlタグのlang=”ja”が継承されるため、p:lang(ja)と同様のスタイルが適用される /
/ もし、htmlタグのlang属性がない場合や、デフォルトのスタイルを完全に分けたい場合は、 /
/ :not([lang]) や :lang() の組み合わせで制御することもある /
解説:
この例では、`html` タグに `lang=”ja”` を設定し、デフォルトのスタイルを日本語向けにしています。
そして、`:lang(en)` を使って、英語の段落 (`lang=”en”`) に対しては、異なるフォントファミリー、ウェイト、色を適用しています。
`lang` 属性が明示的に指定されていない3つ目の `
` 要素は、親要素である `` の `lang=”ja”` を継承するため、日本語向けのスタイルが適用されます。
このように、`:lang()` を使うことで、HTMLを汚さずに、言語ごとの表示を最適化できるんです。
サンプル2: 言語ごとの句読点や記号のスタイル
日本語と英語では、よく使われる句読点や記号の見た目が違いますよね。例えば、引用符のスタイルなんかは、言語によって全く異なる。$:lang()$ なら、そんな細かい部分も制御できます。
“This is a quote in English. Notice the quotation marks.”
「これは日本語の引用です。引用符のスタイルに注目してください。」
For example, a list item might use:
- First item
- Second item
例えば、リスト項目は次のようになります:
- 最初の項目
- 二番目の項目
/ styles.css /
/ デフォルト(ここでは英語を想定)の引用符スタイル /
blockquote {
font-style: italic;
color: #666;
margin: 1em 0;
padding: 0 1em;
border-left: 2px solid #eee;
}
/ 英語の引用符スタイル(::before, ::after 疑似要素で制御) /
blockquote:lang(en)::before {
content: ‘”‘; / 開始引用符 /
font-size: 2em; / 大きく見せる /
color: #aaa;
line-height: 0; / 高さを調整 /
vertical-align: -0.3em; / 位置を微調整 /
margin-right: 0.1em;
}
blockquote:lang(en)::after {
content: ‘”‘; / 終了引用符 /
font-size: 2em;
color: #aaa;
line-height: 0;
vertical-align: -0.3em;
margin-left: 0.1em;
}
/ 日本語の引用符スタイル /
blockquote:lang(ja) {
border-left: none; / 日本語では引用符で示すので、左ボーダーは不要 /
padding: 0;
}
blockquote:lang(ja)::before {
content: ‘「’; / 開始引用符(日本語) /
font-size: 1.5em;
color: #333;
margin-right: 0.2em;
}
blockquote:lang(ja)::after {
content: ‘」’; / 終了引用符(日本語) /
font-size: 1.5em;
color: #333;
margin-left: 0.2em;
}
/ 言語ごとのリストマーカー /
ul {
list-style-type: disc; / デフォルト /
}
/ 英語のリスト項目マーカー(例: シンプルな円) /
ul:lang(en) li {
list-style-type: circle;
color: #444;
}
/ 日本語のリスト項目マーカー(例: 点) /
ul:lang(ja) li {
list-style-type: disc;
color: #222;
}
解説:
この例では、`blockquote` 要素の引用符のスタイルを、`:lang()` を使って言語ごとに変えています。
英語では `::before` と `::after` 疑似要素で `” “` を挿入し、日本語では `「` と `」` を挿入しています。
さらに、リスト (`ul`) のマーカーの種類も言語によって変える例も追加しました。
このように、`:lang()` は、単にテキストの色やフォントを変えるだけでなく、見た目の細かな部分まで制御できる、非常に柔軟なセレクタなんです。
サンプル3: 言語による状態変化(例: disabled要素の見た目)
これは少し発展的な例だけど、`:lang()` を他の疑似クラスと組み合わせることもできる。例えば、特定の言語圏のユーザーが、無効化されたフォーム要素に対して、特別なフィードバックをしたい場合などだ。
/ styles.css /
/ 全てのdisabled要素の基本スタイル /
input[disabled] {
background-color: #f0f0f0;
color: #999;
cursor: not-allowed;
border: 1px solid #ccc;
padding: 8px;
width: 200px;
}
/ 英語のdisabled要素に対する、さらに具体的なスタイル /
/ 例: 特定の言語圏のユーザー向けに、より目立つように警告色を適用 /
input[disabled]:lang(en) {
background-color: #fff0f0; / 薄い赤系の背景 /
border-color: #ffcccc;
box-shadow: 0 0 5px rgba(255, 150, 150, 0.5); / 警告を示す影 /
}
/ 日本語のdisabled要素に対する、さらに具体的なスタイル /
/ 例: 日本語圏のユーザー向けには、落ち着いた警告色にする /
input[disabled]:lang(ja) {
background-color: #f8f8f8; / 少しだけグレーがかった背景 /
border-color: #e0e0e0;
color: #777;
}
/ focus状態と組み合わせる例(disabledなので基本的には発火しないが、概念として) /
/ input:disabled:lang(en):focus { … } /
解説:
この例では、`disabled` 属性を持つ `input` 要素に対して、`:lang()` と組み合わせてスタイルを適用しています。
`html` タグは `lang=”ja”` ですが、各 `input` 要素に `lang` 属性を個別に指定しています。
`:lang(en)` を持つ `disabled` な `input` は、より目立つように赤系の警告色と影を付けています。
`:lang(ja)` を持つ `disabled` な `input` は、それに比べて落ち着いた警告色にしています。
このように、`:lang()` は、状態を示す疑似クラス (`:hover`, `:focus`, `:active`, `:disabled` など) と組み合わせることで、より複雑で、ユーザーに合わせたインタラクションのデザインを可能にします。
$:lang()$ を使う上での注意点とベストプラクティス
$:lang()$ は強力だけど、使う上でいくつか気をつけておきたいことがある。
- HTMLの `lang` 属性は正確に!:
CSS側でどんなに頑張っても、元となるHTMLの `lang` 属性が間違っていたり、指定されていなかったりしたら、$:lang()$ は正しく機能しない。HTMLの構造をしっかりと設計し、各要素に適切な `lang` 属性を付与することが大前提だ。特に、`` タグの `lang` 属性は、サイト全体のデフォルト言語として非常に重要になる。
- ブラウザの優先順位と継承:
前述したように、`lang` 属性は継承される。もし `` タグに `lang=”en”` が指定されていて、ある `
` 要素に `lang=”ja”` が指定されていたら、その `
` 要素は `ja` として扱われる。より具体的な属性値が優先されるんだ。
また、`:lang(en)` は `:lang(en-US)` よりも広い範囲にマッチする。もし `lang=”en-US”` の要素にだけスタイルを適用したいなら、`:lang(en-US)` と具体的に指定する必要がある。
- Specificity(特異度)を忘れずに:
$:lang()$ も他のCSSセレクタと同様に、特異度を持っている。例えば、`p { … }` よりも `p:lang(en) { … }` の方が特異度が高い。もし、$:lang()$ で指定したスタイルが他のスタイルに上書きされてしまう場合は、特異度を意識してセレクタを調整する必要があるかもしれない。
- パフォーマンスへの影響は?:
最近のブラウザは賢いので、$:lang()$ の使用で著しくパフォーマンスが低下することは稀だ。しかし、過度に複雑なセレクタを多用したり、ものすごく大量の要素に対して細かく$:lang()$ を適用したりすると、わずかながら影響が出る可能性もゼロではない。基本的には、必要十分な範囲で、分かりやすく使うのが一番だ。
まとめ:$:lang()$ は、国際化対応の「隠し味」
さて、今日は$:lang()$ 疑似クラスについて、その基本的な使い方から、ブラウザの裏側の動き、そして実践的なコード例まで、みっちり解説してきた。
「へー、こんなのあるんだ!」って思ってくれたなら嬉しい。$:lang()$ は、Webサイトの国際化対応を進める上で、HTMLの構造をクリーンに保ちつつ、言語ごとの細やかなデザイン調整を可能にしてくれる、まさに「隠し味」のような存在なんだ。
もちろん、全てのプロジェクトで必須というわけではない。でも、多言語対応を考えている、あるいは既に実施しているプロジェクトに携わるなら、この$:lang()$ という武器を、ぜひ君のエディタの引き出しに忍ばせておいてほしい。きっと、君のフロントエンド開発の幅を、さらに広げてくれるはずだから。
もし「こんな使い方もあるよ!」とか、「こういうケースで困ってるんだけど…」なんてことがあれば、いつでも声をかけてくれ。現場で培った知見を、惜しみなく共有させてもらうぜ!
それでは、また次の記事で! Happy Coding!

コメント