CSSの特徴をしっかりと把握しよう

CSSの特徴を把握しよう

CSSにはいくつかの特徴があります。これらを早いうちに理解しておくと、ウェブ制作の作業効率が格段に上がります。逆に、これらの特徴を理解しておかないと、無駄な記述を増やしたり思い通りに表示されない現象に遭遇します。細かい部分に着手する前に、全体像を把握しておきましょう。

カスケード

CSSは「Cascading Style Sheets(カスケーディング・スタイル・シート)」の略です。そのため、名前の由来となった「カスケード」の概念を正しく理解することが最初の第一歩です。カスケードを和訳すると「滝状の流れ」です。それをイメージすると、上から下へ流れる水となります。つまり、CSSは上から下へ処理されていくスタイルシートなのです。

具体的に言うと、先に書かれたスタイルは後に書かれたスタイルに上書きされます。同じ名前のセレクタに別のプロパティが指定されていれば追加されます。同じ名前のセレクタの同じプロパティに別の値が指定されていれば、先に書かれていた内容が破棄されて後に書かれたものが採用されます。もちろん、全ての内容が重複していなければ上書きは起こりません。


/* 同じセレクタに別のプロパティがあれば */
h1 {	font-size: 1.5rem;}
h1 {	color: #600;}

/* 追加される */
h1 {
	font-size: 1.5rem;
	color: #600;
}

/* 同じセレクタのプロパティに別の値が指定されていれば */
h1 {	font-size: 1.5rem;}
h1 {	font-size: 2rem;}

/* 上書きされる */
h1 {
	font-size: 2rem;
}

このように、CSSは上から下へ流れるように処理されていくものだ、ということを覚えておいて下さい。ただし、以降で説明する「詳細度・特異性」によって採用されるスタイルの優先度が変わります。

継承

親要素に指定されたスタイルの中には、子要素にも引き継がれるものがあります。これを「継承」と言います。プロパティによって継承「する/しない」の初期値が定義されています。これらは継承を制御するプロパティによって個別に変更できます。

例えば、ある親要素の文字色を指定した場合、その値は子要素にも引き継がれます。


<p style="color: #990000;">
	テキスト <span style="font-weight: bold;">太字の子要素</span> テキスト。
</p>

上記の例では、<span>に囲まれた文字列が、太字として表示されるだけでなく、赤い文字として表示されます。これは親要素に指定されたスタイルが子要素へと継承されたことを意味します。実際に<span>に対して文字色の変更は指定されていませんが、そのように表示されるからです。

続いて、継承されない例を見てみましょう。先ほどの内容に横幅と外枠のスタイルを追記してみます。しかし、これらの装飾は子要素には継承されません。


<p style="color: #990000; width:80%; border:1px solid #000099;">
	テキスト <span style="font-weight: bold;">太字の子要素</span> テキスト。
</p>

継承の既定値は、一般的に多くの人々が便利だと感じる振る舞いが採用されています。色であれば最初から継承した方が楽ですが、枠線が全ての子要素に継承されたら不便です。これは制作者側でいつでも変更ができます。プロパティの値に以下のキーワードを指定すると、求める効果が得られます。

継承を制御する

inherit
継承を有効にします。この値が追加されたプロパティは親要素と同じスタイルを優先させます。
initial
ブラウザのデフォルト・スタイルシートで設定されている値と同じものにします。デフォルトのスタイルが未設定だった場合は、代わりにinheritと同様の振る舞いをします。
unset
プロパティの値が自然に継承されるものであれば、inheritと同じ動作をします。そうでない場合は、initialと同じように動作します。

<div class="sample-block">
	<p class="item1">.item1: inherit</p>
	<p class="item2">.item2: initial</p>
	<p class="item3">.item3: unset</p>
</div>

.sample-block {
	padding: 0.5rem;
	border: 3px solid #ccc;
	color: #f00;
}
.sample-block > p {
	margin-block: 0.5rem;
}
.item1 {
	border: inherit;
	color: inherit;
}
.item2 {
	border: initial;
	color: initial;
}
.item3 {
	border: unset;
	color: unset;
}

詳細度・特異性

詳細度または特異性(Specificity)は、各要素に適用されるスタイルをブラウザが決定するために用いるアルゴリズムです。複数のセレクタが同じ要素に対して違うスタイルを指定している場合に、どちらを採用すべきかを決める判断基準となります。

基本的には、より具体的なセレクタを尊重します。例え話で言うと、宇宙よりも銀河、銀河よりも太陽系、太陽系よりも地球の方が身近に感じられる、といった感覚と同じです。汎用的な要素の名前よりも、idclass名の方がより具体的です。そして一番具体的なのは、要素そのものにstyle属性を指定する方法です。

例えば、カスケードの特性を活かしてマークアップの後半で最初に書いたスタイルを上書きしようとします。しかし、抽象的なセレクタで指定したスタイルは具体的なセレクタを上書きできません。そのため、ルールに従って書いたつもりのCSSが正しく表示されないという悩みに遭遇します。その問題の多くは、詳細度を理解することで解決します。

ブラウザはスタイルを決定する上で以下の三つの判断材料を持ちます。

  • ソースオーダー(Source order):カスケードによる優先度
  • 詳細度(Specificity):ポイントによる重み付け
  • 重要性(Importance):恣意的な重要性

この中で、詳細度にはセレクタに重み付けを行うポイントが用意されています。各ポイントは対応する列に与えられます。このポイントは加算されますが、桁をまたいだり繰り上がったりすることはありません。例えば、一番低い桁のポイントが10以上溜まっても、高い桁の1ポイントには勝てません。

種別 重み 概要
インラインスタイル 1-0-0-0 1000ポイントの重みを持つ
ID列 1-0-0 100ポイントの重みを加算
CLASS列 0-1-0 10ポイントの重みを加算
TYPE列 0-0-1 1ポイントの重みを加算
値なし 0-0-0 ポイントを加算しない

インラインスタイルの詳細度

インラインスタイルは、要素のstyle属性に指定される値のことです。要素に直接指定しているものであり、最も具体的な詳細度を持ちます。ポイントの列は1-0-0-0であり、他のセレクタでは干渉できない桁の数値を持つため、必ずインラインスタイルが優先されます。ヘッダーや外部ファイルにいかなるセレクタが定義されていたとしても、インラインスタイルは同じプロパティの値を上書きします。

どうしてもインラインスタイルを打ち消したい場合は、プロパティの値に!importantのキーワードを追加します。これはイレギュラーな操作であるため、多用は禁物です。また、インラインスタイルも局所的なソースコードを増やす原因になるため、できる限りidclassで管理しましょう。


<!-- style属性の内容は詳細度 1-0-0-0 -->
<div style="color: red;" class="item" id="name">
Inline style text.
</div>

/* 詳細度 0-1-0-0 で上書きできない */
#id {	color: #036;}

/* 詳細度 0-0-1-0 で上書きできない */
.class {	color: #063;}

/* 詳細度 0-2-12-0 でも上書きできない */
#id1 #id2.c1.c2.c3.c4.c5.c6.c7.c8.c9.c10.c11.c12 {}

/* 唯一 !important を使うと優先される */
.item {	color: #063; !important}
#name {	color: #036; !important}

ID列の詳細度

ID列の詳細度は、IDセレクタで指定された内容に対して与えられます。ポイントの列は1-0-0です。HTMLの文法では、id属性の値はひとつのページにひとつだけ設置して良いことになっているため、固有の識別子として扱えます。そのため、詳細度はインラインスタイルに次いで二番目に高い桁となっています。


/* 詳細度 1-0-0 */
#container {}

/* 詳細度 2-0-0 */
#container #block {}

/* 詳細度 1-1-0 */
#container .class {}

/* 詳細度 1-1-1 */
#container .class > p {}

/* 詳細度を上げたくない場合 */
:where(#id) {}

CLASS列の詳細度

CLASS列の詳細度は、CLASSセレクタ属性セレクタ擬似クラスセレクタで指定された内容に対して与えられます。ポイントの列は0-1-0です。HTMLの文法では、class属性の値はひとつのページにいくつでも設置して良いことになっています。そのため、詳細度はIDセレクタよりも低い三番目の桁となっています。


/* 詳細度 0-1-0 */
.block-group {}

/* 詳細度 0-1-0 */
[class="block-group"] {}

/* 詳細度 0-2-0 */
.menu .item {}

/* 詳細度 0-2-0 */
.menu > [data-item] {}

/* 詳細度 1-1-0 */
.class #id {}

/* 詳細度 1-1-1 */
.class #id > section {}

/* 詳細度 0-2-1 */
a.link:hover {}

/* 詳細度を上げたくない場合 */
:where(.class) {}

TYPE列の詳細度

TYPE列の詳細度は、要素セレクタ擬似要素セレクタで指定された内容に対して与えられます。ポイントの列は0-0-1です。HTMLであらかじめ定義されている要素のタグ名などを指すため、汎用的なセレクタとして用いられます。任意で名前を決められるidclassよりも抽象的であることから、最も低い桁のポイントとなります。


/* 詳細度 0-0-1 */
p {}

/* 詳細度 0-0-2 */
header nav {}

/* 詳細度 1-0-1 */
header #logo {}

/* 詳細度 0-1-1 */
header .banner {}

/* 詳細度 0-0-2 */
li::before {}

/* 詳細度を上げたくない場合 */
:where(ol, ul) {}

値なしの詳細度

詳細度の値を持たないセレクタは、ユニバーサルセレクタ*)および:where()擬似クラスです。これらを使用して指定したスタイルは、詳細度のポイントに影響を与えません。

ユニバーサルセレクタ*)は、一般的にソースコードの上部に配置され、ブラウザの既定値を初期化するために使われます。そこで指定された内容は、0-0-0のポイントであるため、後に配置されたセレクタでいくらでも上書きできます。

:where()擬似クラスは、それ自体では詳細度に影響を及ぼしませんが、引数に指定されたセレクタの詳細度を0-0-0にする効果を持ちます。例えばIDセレクタCLASSセレクタで指定するスタイルの詳細度を上げたくない場合に、:where()擬似クラスで囲って低い詳細度を保つことができます。

また、セレクタ同士を関連付ける結合子 <+~||)は詳細度の重み付けには影響を与えません。結合子を使ってセレクタが対象にする要素を具体的に絞り込むことと、詳細度を上げることは関係がないということです。


/* 詳細度 0-0-0 */
* {}

/* 詳細度 0-0-0 */
:where(#id) {}

/* 詳細度 0-0-0 */
:where(.class) {}

/* 詳細度 0-0-0 */
:where(section > p) {}

重要性(!important)

CSSは、ブラウザのデフォルト・スタイルシート、ユーザーが設定したスタイルシート、ページ制作者が用意したスタイルシートの順に優先されます。つまり、制作者が用意したスタイルシートは、あくまでユーザーに提案するものであって、閲覧する側が任意のスタイルを表示するように設定していた場合は無効となります。

しかし、どうしてもこちらで意図したように表示しないと不都合が生じてしまう場合には、特定のプロパティの優先度を高くするように命令することができます。

CSSでは、特定のプロパティに!importantを指定すると、そのプロパティの優先度が高くなります。基本的な優先度を超えて強制的にスタイルを適用させたいプロパティがある場合に活用して下さい。

ただし、絶対に必用な箇所以外は使用を控えて下さい。カスケードのルールや標準仕様を超えてスタイルを強制するやり方は、デバッグを困難にするだけでなく、閲覧者の不快を誘う可能性があります。

h1 {
	color: #ff0000 !important;
} 

上記の例は、優先的に文字を赤くしたい場合に指定する内容になります。

idとclass名をセレクタにできる

同じ種類のタグに違うスタイルを適用したい場合に、id属性やclass属性で命名した文字列をセレクタにできます。全てのHTML要素はグローバル属性を指定できるため、どのタグに対してもid属性やclass属性による命名が可能です。

同一のページに複数の同一要素があり、個別のスタイルを適用したい場合や、複数のページの中に同じパターンでスタイルを適用したい場合に、名前とスタイルを共通化しておくと管理がとても楽になります。

id属性の例
<div id="content">
class属性の例
<div class="box">
id名をセレクタにする場合
id名の先頭に「#」を付けて指定(#content)
class名をセレクタにする場合
class名の先頭に「.」を付けて指定(.box)

以下の例では、コンテンツを囲う<div>要素に対してid属性やclass属性を指定し、それをセレクタにして個別のスタイルを設定しています。


<div id="menu">
	<ul>
		<li>メニュー01</li>
		<li>メニュー02</li>
		<li>メニュー03</li>
		<li>メニュー04</li>
	</ul>
</div>

<div class="contents">
コンテンツ、コンテンツ、コンテンツ、コンテンツ
</div>
#menu {
	width: 300px;
	float: left;
	font-size: 14px;
	font-weight: bold;
}
.contents {
	width: 500px;
	float: right;
}

このように、管理の面から見てもid属性やclass属性を活用してスタイルを分かりやすく整理しておくことをお勧めします。

CSSリファレンス一覧