Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 12261] ファイルの概要

このコミットは、Go言語のドキュメントサイトで使用されているdoc/style.cssファイルに対する変更です。このファイルは、Go言語の公式ドキュメントや関連ページの視覚的なスタイルを定義するCascading Style Sheets (CSS) ファイルであり、フォント、色、レイアウト、要素の配置など、ウェブページの表示に関するあらゆる側面を制御しています。

コミット

  • コミットハッシュ: bfdc3baa1e6a5d18dbfb85081f223192dd2fb210
  • Author: Stefan Nilsson snilsson@nada.kth.se
  • Date: Wed Feb 29 09:38:58 2012 +1100

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/bfdc3baa1e6a5d18dbfb85081f223192dd2fb210

元コミット内容

doc/style.css: make selectors more selective.

Change #foo to div#foo to avoid selecting headings
with anchor foo, such as <h1 id="foo">.

(A more extensive change would be to use class
selectors for styling. Perhaps this is better, since id:s
should be unique within a document according to
http://www.w3.org/TR/CSS2/selector.html#id-selectors)

R=golang-dev, gri, adg
CC=golang-dev
https://golang.org/cl/5702044

変更の背景

このコミットの主な目的は、doc/style.cssにおけるCSSセレクタの**特異性(specificity)**を高めることです。元のCSSでは、#fooのようなIDセレクタが使用されていました。IDセレクタは非常に高い特異性を持つため、特定のIDを持つ要素を正確にターゲットにするのに適しています。しかし、HTMLのセマンティクスにおいて、id属性はドキュメント内で一意であるべきだとされています。

問題は、<h1>タグのような見出し要素にアンカーとしてid属性が設定されている場合、例えば<h1 id="foo">のようなケースで発生しました。もしCSSに#foo { /* スタイル */ }というルールがあった場合、これはdiv要素だけでなく、id="foo"を持つh1要素にも適用されてしまいます。これは意図しないスタイルの適用を引き起こす可能性があり、特に見出しのスタイルが崩れるなどの問題が生じることが考えられます。

この変更は、このような意図しないスタイルの適用を防ぐために、セレクタをより具体的に(div#fooのように要素名を付加して)指定することで、特定の要素タイプにのみスタイルが適用されるようにすることを目的としています。コミットメッセージにもあるように、より広範な解決策としては、スタイリングにIDセレクタではなくクラスセレクタを使用することが挙げられていますが、このコミットではより限定的な修正が適用されています。

前提知識の解説

CSSセレクタ

CSSセレクタは、HTMLドキュメント内のどの要素にスタイルを適用するかを決定するためのパターンです。様々な種類のセレクタがあり、それぞれ異なる方法で要素を選択します。

  • タイプセレクタ(要素セレクタ): HTML要素のタグ名に基づいて要素を選択します。例: p (すべての<p>要素を選択), div (すべての<div>要素を選択)。
  • IDセレクタ: HTML要素のid属性の値に基づいて要素を選択します。#記号の後にID名を記述します。例: #header (IDがheaderの要素を選択)。HTMLドキュメント内でid属性の値は一意であるべきです。
  • クラスセレクタ: HTML要素のclass属性の値に基づいて要素を選択します。.記号の後にクラス名を記述します。例: .button (クラスがbuttonの要素を選択)。複数の要素に同じクラスを適用できます。
  • 子孫セレクタ: スペースで区切られたセレクタのリストで、ある要素の子孫である要素を選択します。例: div p (div要素内のすべての<p>要素を選択)。
  • 複合セレクタ: 複数のセレクタを組み合わせて、より具体的な要素を選択します。例: div#nav (IDがnavdiv要素を選択)。

CSSの特異性(Specificity)

CSSの特異性とは、複数のCSSルールが同じ要素に適用される場合に、どのルールが優先されるかを決定するアルゴリズムです。特異性は、セレクタの種類と数に基づいて計算されます。

  • インラインスタイル: HTML要素のstyle属性に直接記述されたスタイルは、最も高い特異性を持ちます。
  • IDセレクタ: IDセレクタは高い特異性を持ちます。
  • クラスセレクタ、属性セレクタ、擬似クラス: これらは中程度の特異性を持ちます。
  • タイプセレクタ(要素セレクタ)、擬似要素: これらは低い特異性を持ちます。
  • ユニバーサルセレクタ (*): 最も低い特異性を持ちます。

特異性の計算は、通常、(IDの数, クラス/属性/擬似クラスの数, 要素/擬似要素の数) の3つの数値の組み合わせで行われます。例えば、#navは(1,0,0)、div#navも(1,0,0)ですが、div#navは要素セレクタとIDセレクタの組み合わせであり、より意図が明確になります。このコミットの変更は、特異性の値を直接的に大きく変えるというよりは、セレクタの意図を明確にし、誤った要素への適用を防ぐことに主眼が置かれています。

W3CのIDセレクタに関する推奨事項

W3C (World Wide Web Consortium) のCSS仕様では、IDセレクタについて「IDはドキュメント内で一意であるべき」と明確に述べられています。これは、IDが特定の単一の要素を識別するために設計されているためです。この原則に従うことで、JavaScriptからの要素へのアクセスや、CSSでの特定の要素へのスタイリングが予測可能になります。

参照: W3C CSS2.1 Specification - 6.3.3 ID selectors

技術的詳細

このコミットで行われた技術的な変更は、既存のIDセレクタの前に対応するHTML要素のタイプセレクタを追加することです。例えば、#navというセレクタはdiv#navに変更されています。

この変更の技術的な影響は以下の通りです。

  1. セレクタの意図の明確化: div#navと記述することで、「IDがnavであるdiv要素」というように、セレクタがターゲットとする要素のタイプが明確になります。これにより、例えば<h1 id="nav">のような要素が誤ってスタイルされることを防ぎます。
  2. 特異性の維持と精度の向上: IDセレクタは単独でも高い特異性を持っていますが、要素セレクタを追加しても特異性の計算値は変わりません(IDの数が同じため)。しかし、セレクタがより具体的になることで、意図しない要素へのスタイルの適用を防ぎ、結果としてスタイルの適用精度が向上します。
  3. 保守性の向上: セレクタの意図が明確になることで、将来的にCSSを修正したり、新しいスタイルを追加したりする際に、どの要素にスタイルが適用されるのかが分かりやすくなり、コードの保守性が向上します。
  4. W3Cの推奨事項への準拠: IDは一意であるべきという原則は、主にJavaScriptからのアクセスやアンカーリンクの動作に関連しますが、CSSにおいても、IDセレクタをより具体的にすることで、そのIDが特定の要素タイプに属するという意図を強調できます。

この変更は、CSSのベストプラクティスに従い、より堅牢で予測可能なスタイルシートを構築するための一歩と言えます。

コアとなるコードの変更箇所

このコミットでは、doc/style.cssファイル内で、多くのIDセレクタ(例: #nav, #heading, #topbarなど)が、対応する要素タイプを前置した複合セレクタ(例: div#nav, div#heading, div#topbarなど)に変更されています。

以下に、変更の一例を示します。

--- a/doc/style.css
+++ b/doc/style.css
@@ -83,10 +95,11 @@ dl {
 dd {
 	margin: 2px 20px;
 }
-dl, dd {
+dl,
+dd {
 	font-size: 14px;
 }
-#nav table td {
+div#nav table td {
 	vertical-align: top;
 }
 
@@ -102,50 +115,50 @@ table.dir td {\n 	color: #AA0000;\n }\n \n-#heading {\n+div#heading {\n 	float: left;\n 	margin: 0 0 10px 0;\n 	padding: 16px 0;\n 	font-size: 26px;\n 	font-weight: normal;\n }\n-#heading a {\n+div#heading a {\n 	color: #222;\n 	text-decoration: none;\n }\n \n-#topbar {\n+div#topbar {\n 	background: #E0EBF5;\n }\n \n body {\n 	text-align: center;\n }\n-#page,\n-#topbar .container {\n+div#page,\n+div#topbar .container {\n 	clear: both;\n 	text-align: left;\n 	margin-left: auto;\n 	margin-right: auto;\n 	width: 900px;\n }\n-#plusone {\n+div#plusone {\n 	float: right;\n }\n-#plusoneRoot {\n+div#plusoneRoot {\n 	float: right;\n }\n \n-#copyright {\n+div#copyright {\n 	color: #666;\n 	font-size: 14px;\n 	margin: 40px 0;\n }\n \n-#menu > a,\n-#menu > input,\n-#learn .buttons a,\n-#blog .read a {\n+div#menu > a,\n+div#menu > input,\n+div#learn .buttons a,\n+div#blog .read a {\n 	padding: 10px;\n \n 	text-decoration: none;\

コアとなるコードの解説

上記の差分では、例えば#nav table tddiv#nav table tdに、#headingdiv#headingに、#topbardiv#topbarにそれぞれ変更されています。

  • 変更前 (#nav table td): このセレクタは、IDがnav任意の要素の子孫であるtable要素内のtd要素にスタイルを適用します。もし<h1 id="nav">のような要素が存在した場合、その見出し内のtable要素にもスタイルが適用される可能性がありました。
  • 変更後 (div#nav table td): このセレクタは、IDがnavである**div要素**の子孫であるtable要素内のtd要素にのみスタイルを適用します。これにより、div要素以外の要素(例えばh1要素)がnavというIDを持っていても、このスタイルは適用されなくなります。

同様に、#headingからdiv#headingへの変更も、IDがheadingであるdiv要素にのみスタイルを適用することを保証します。

この変更は、CSSのセレクタをより厳密にすることで、意図しない要素へのスタイルの漏れを防ぎ、スタイルシートの堅牢性を高めるためのものです。これは、大規模なウェブサイトやアプリケーションにおいて、CSSの衝突や予期せぬ表示崩れを防ぐ上で非常に重要なプラクティスです。

関連リンク

参考にした情報源リンク