はじめに
谷拓樹さんのWEB制作者のためのCSS設計の教科書を読み、自分なりにまとめたものです。
1章の記事はこちらから↓
http://qiita.com/poster-keisuke/items/88930d3bc19f03b864fc
※追記
2016/09/22
・コード部分を見やすく変更しました。
・3章のリンクを貼りました。
CSSセレクタと詳細度
カスケーディングの基本
CSSはカスケーディング・スタイルシートの略。カスケード(滝)のように先に宣言されたルールセットが、あとに宣言されるルールセットによって継承、上書きされる。
.primary {
color: red;
}
.primary {
color: blue; #こちらのルールが優先される
}
<button class=“button save”> 保存する </button>
.button {
display: inline-block;
border: 1px solid #000;
background-color: #EEE;
color: #000;
…...
}
.save {
border-color: green; #ボーダーの色を上書き
background-color: lightgreen; #背景色を上書き
color: green; #文字の色を上書き
}
こちらもあとに記述されている .saveが .buttonのルールを上書きしている。
ただしこれらは、同じ詳細度である、ということが前提である。
詳細度
CSSのセレクタには、詳細度という条件がある。セレクタの内容がより具体的・詳細であるほど、そのルールが優先される。
- !important
- インライン記法(style属性)
- IDセレクタ
- クラスセレクタ・属性セレクタ・擬似クラス
- 要素セレクタ・擬似要素
- ユニバーサルセレクタ
!important
切り札的な宣言。最も優先されるルールである。
.primary {
color: green !important;
}
基本的には避けたい記法。これが多用されている状態ということは、既存のCSSが高い詳細度のセレクタで溢れてしまっているということ。
しかし、能動的、意図的に使うことが許容される場合もある。(第3章にて)
インライン記法(style属性)
<button style=“color: green"> 保存する </button>
HTMLのstyle要素やCSSファイルに記述されたルールよりも優先される。
そもそもスタイルはCSSで一元管理するほうが好ましいので、多様は禁物。
デバッグの際に一時的にスタイルを持たせたいとか、本当にその場でしか使わない、CSSファイルに記述したくないといった場合。
また、Javascriptによってstyle属性に直接スタイルを書き込む場合もあります。例えば、表示・非表示のための display: none;などです。
しかしこのような場合においても、スタイルはCSSにファイルに持たせて、Javascriptでクラスをつけたり外したりすることが好ましい方法です。
IDセレクタ
IDはドキュメント(ページ)内で一度だけ使うことができる。HTMLにおいて、id=“foo”と振られた要素があるとすれば、そのfooというIDは同一ページ内で一度しか利用できない。
固有の識別子によって、セレクタとしては最も高い詳細度になる。
#primary {
color: green;
}
.primary {
color: red;
}
クラスセレクタ・属性セレクタ・擬似クラス
.primary { #こちらのルールが適応される
color: red;
}
.button {
color: green;
}
[class=“primary”] #class属性にprimaryだけが入っている要素を選択
color: green; #こちらのルールが適応される
}
.button {
color: green;
}
.button:first-child { #最初の子要素を選択
color: green;
}
.button {
color: blue;
}
要素セレクタ・擬似要素
要素を直接選択するセレクタは、IDやクラスよりも詳細度は低くなる。
::after ::beforeも同じ
ユニバーサルセレクタ
*{ #全ての要素のmarginとpaddingを0にする
margin: 0;
padding: 0;
}
詳細度の計算
各セレクタの優先順位は前述の通り。実際はこれらが組み合わさることで更に複雑になる。
例えば、1つのクラスセレクタと2つのクラスセレクタのルールセットがあった場合、後者が優先される。
.widget .title { #こちらのルールが適応される
font-size: 16px;
}
.title {
font-size: 19px;
}
計算ツール↓
https://specificity.keegan.st/
数に関係なく、
- !important
- インライン記法(style属性)
- IDセレクタ
- クラスセレクタ・属性セレクタ・擬似クラス
- 要素セレクタ・擬似要素
- ユニバーサルセレクタ
以上のものが使われる場合には、それらが最優先される。
セレクタをより安全でシンプルなものに
マークアップを考えて構造を元に素直にセレクタを書いていくと、セレクタは多く、複雑になる。
その結果、セレクタの詳細度を高めて、メンテナンス効率を下げることになる。
以下は、CSSセレクタのリファクタリングについて
要素セレクタを省略する
h2 .title {
font-size: 1.4em;
font-weight: bold;
}
ul.links li {
padding-left: 20px;
background-color: red;
}
こうした要素を指定することは、詳細度を高める為に過ぎない。セレクタとしては省略してもよいはず。
.title {
font-size: 1.4em;
font-weight: bold;
}
.links li {
padding-left: 20px;
background-color: red;
}
セレクタを短くする
.links li a {
display: block;
}
.links a {
display: block;
}
不要なセレクタを省略することによって、単純に詳細度の問題を解決するだけではなく、特定の要素への依存を減らすことによって、可搬性(移植しやすさ)を高める。
セレクタを限定的にする
.links a {
display: block;
}
.links > a {
display: block;
}
子孫セレクタ(子要素以外全ての要素、つまり孫となる要素も含めて)ではなく、子供セレクタ(直下の要素のみ)を利用する
クラスセレクタを利用する
<div id=“sidebar">
<ul>
<li><a href =“menu”>メニュー</a></li>
<li><a href =“menu”>メニュー</a></li>
</ul>
</div>
#sidebar {
border: 1px solid #ccc;
….
}
#sidebar > ul > li {
border-bottom: 1px dashed #ccc;
}
#sidebar > ul > li > a {
display: block;
color: #489;
….
}
<div id=“sidebar">
<ul class=“menus">
<li><a href =“menu”>メニュー</a></li>
<li><a href =“menu”>メニュー</a></li>
</ul>
</div>
#siledbar {
border: 1px solid #ccc;
….
}
.menus > ul > li {
border-bottom: 1px dashed #ccc;
}
.menus > ul > li > a {
display: block;
color: #489;
….
}
<div id=“main”>…</div>
<div id=“sidebar">…</div>
<div id=“navigation">…</div>
このリファクタリングのポイントは詳細度の問題だけではない。
例えば、2カラムのwebサイトだったとして、メインコンテンツエリアと、サイドバーエリアに分かれているとする。
しかしサイトの情報量が増えたり、デザインの変更等によってページの幅を広げ3カラムにする事になった場合もう一つ隣にサイドバーが増えたとする。
そうなった場合、#sidebarに依存していたマークアップ上での変更はもちろん、CSS上でも#sidebarを#navigationに変更塩無くてはならないかもしれない。
これだけでもCSS上でも側の修正という手数が増えているわけがだが、一度変更したものを再び元に戻すとか、#sidebarA #sidebarBにするという事になりうるかもしれない。
場所に依存したセレクタである限りは、場所が変われば使えなくなるしその都度書き換えなければならない。
しかし、.menusというクラスセレクタでまとめた方のコードであれば、マークアップだけ置き換えれば、どの場所にあってもメニューリストの機能・体裁に変化はない。
こうした設計はコンポーネント設計と呼ばれ、まとまったルールセットを一つの部品として考えて設計する手法である。
次回3章につづく
http://qiita.com/poster-keisuke/items/a50560aa60e320444433