CSS Coding Guide
ひとまず書き殴った。
プロジェクトでスタイルシートの「一貫性を保つ」ためのドキュメント。
このルールを守っていくのは難しい(しんどい)場合はドキュメント内容を見直そう。
このドキュメントでは以下の内容を含んでる。
- エンコードなどのメタルール
- インデントなどの書式ルール
- ネストの上限などのコーディングルール
メタルール
エンコード
UTF-8 を使用する:
@charset "UTF-8";
コメント
普通のコメントは普通に、 /* */
形式で書く。
TODO コメントは以下のように書く:
.module { backround-image: url(//lorempixel.com/200/200/); /* TODO: change dummy image */ }
Sass 使ってる場合、スタイルガイド用のコメントはコンパイル後消されるように //
を使って書く:
// ## Module // ``` // <div class="module">module</div> // ```
書式ルール
一般的な書式
- プロパティの前にはスペース2つでインデント
:
の前にはスペースを1つ{
の前にはスペースを1つ{
の後は改行- セレクタ内最後のプロパティの後は改行
}
の後は改行し、 1行空ける- 行末のスペースは削除
- 小文字のみを使用
これら満たした CSS の構文:
/* General Format */ .format { display: block; border: 1px solid red; background-color: tomato; }
「0」のときの単位の省略
「0」のときは単位を省略する:
.format { margin: 0; padding: 0; }
小数点の頭の「0」の省略
小数点の頭の「0」は省略:
.format { margin: .5em; text-shadow: 0 1px 0 rgba(0,0,0,.4); }
URI 値の引用符の省略
URI 値の引用符は省略:
.format { background-image: url(...); }
URI 値のプロトコルの省略
URI 値のプロトコル ( http:, https: )は省略:
/* NG */ .format { background-image: url(http://www.google.com/); } /* OK */ .format { background-image: url(//www.google.com/); }
コーディングルール
id か class か
ページ内に 1度だけ出現するものには id を使い、そうでない場合は class を使う。どちらか迷ったら class を使う。
さらに言うなら、基本的には一部のコンテンツを指定したい場合や SMACSS カテゴリーでいうレイアウト以外に id を使うべきではなく、他では class を使うべきである。
- 良い id の例: header, main, footer
- 悪い id の例: navigation, list, contents name
ID やクラスの命名
大前提
コンポーネントの意味がわかる名前で書く。
連番や見た目を表した名前は使用してはならない。
/* NG: 連番(意味がわからん) */ .message-1 { ... } .message-2 { ... } /* NG: 見た目を表してる */ .button-red { ... } .clear { ... } /* OK: 役割を表してる */ .message-user { ... } .message-shop-owner { ... } .list { ... }
基本
ハイフン ( -
) とアンダースコア ( _
) を使って BEM のルールで書く。
BEM ( Block, Element, Modifier ) のルール:
- Block .. アプリケーションの構成要素 に当たるもの。単体の Block (状況によるけど table とか)もあれば複数の Block を含む複合物(ロゴやメニューを含むヘッダーとか)のものもある。
- Element .. Block の構成要素 (検索 Block 内の入力欄とボタンとか)。
- Modifier .. 元となる Block や Element で一部スタイルの変更が必要な時にに使うもの 。
BEM について詳細が知りたい場合は公式サイトを読むのが一番いいけど、「英語プギャー」ってなったら自分で書いたブログとか他の人が上手くまとめてるやつ見て。
単語の省略
1単語の中でのみ省略を許す。
複数単語が連なる際、それらを省略しようとしてはならない。
/* NG */ .fnav { ... } /* OK */ .footer-navigation { ... } .nav { ... }
また、いつでも省略可能なものとしては以下を上げている。
これら以外に省略して記述したい単語がある場合は検討の末、ドキュメントに残すこと。
一般的に省略されるものとして省略を許している単語:
- navigation => nav
- previous => prev
- thumbnail => thumb
- picture => pic
- background => bg
- banner => bnr
- image => img
接頭辞としての省略:
- button => btn (
class="button btn-primarily"
のようなマルチクラスの指定で、モジュールに接頭辞を付ける場合に限る ) - icon => ico (
class="icon ico-message"
のようなマルチクラスの指定で、モジュールに接頭辞を付ける場合に限る ) - layout => l ( SMACSS のレイアウトカテゴリー内で使う場合に限る )
- grid => g ( SMACSS のレイアウトカテゴリー内で使う場合に限る )
- javascript => js ( Javascript で使うクラスとスタイルのクラスを分ける場合に限る )
ディレクトリ構成
SMACSS カテゴリーで分ける。
カテゴリー:
- ベース
- レイアウト
- モジュール
- ステート(状態)
- テーマ
ディレクトリ構成の例:
stylesheets/ | |-- base/ | | | |__ base.css | |-- layout/ | | | |-- laytout.css | | | |__ grid.css | |-- module/ | | | |-- button.css | | | |-- form.css | | | |__ table.css | |-- state/ | | | |__ state.css | |-- theme/ | | | |-- valentine.css | | | |__ xmas.css | |__ partial/ | |__ colors.css
Sass で Partial ファイルを取り扱う場合はカテゴリーディレクトリと同じ階層に置く:
stylesheets/ | |-- .../ | |-- theme/ | |__ partial/ | |__ colors.css
SMACSS について詳細が知りたい場合は本が出てるからそれ見て。「100ページ読むのはだりぃ〜 」って感じなら.. 自分で書いた本の要約でも見て。
プロパティの列挙順
以下のグループで分けて書く:
- ボックス(表示とポジション)
- ボーダー
- バックグラウンド
- テキスト
- その他
ボックスには margin
や position
の指定、ボーダーには border
、バックグラウンドには background
、テキストには font
や color
や lin-height
や text-align
、その他には clear
や cursor
の指定を書く。グループ内でのプロパティの列挙順はできるだけ統一する(できるだけ合わせる. レベルでいい)。
プロジェクトごとにプロパティの列挙順一覧を作成する。
ベンダープレフィックス
以下の順序で書く:
- -webkit-
- -moz-
- -ms-
- -o-
- none
ブラウザのアップデートによりベンダープレフィックスのサポートが不要になったものは順次消していこう。
カラーコード
HEX 形式で指定する。
HEX 形式のカラーコード 3文字で表記できるものは 3文字で指定する。
/* NG */ .module { color: ##000000; background-color: ##ffffff; } /* OK */ .module { color: ##000; background-color: ##fff; }
これは備考だけど、IE8 以下の対応を考えてるなら CSS3 から追加された RGBA, HSLA 形式は使わないほうがいい。Sass なんかを使ってる場合はコンパイル時に HEX 形式に変換するといい。
px か em か
本当は em
使ったほうがいいかもしれないけど、今はまだ px
使おう。
僕にはまだ em
を使ってちゃんとプロダクトを組み上げる自身がないんだ。
rem
という手段も検討してみよう。
セレクタ
ユニバーサルセレクタ ( *
) は使用してはならない。適用範囲が把握しにくいことや全てを走査して適用していくのでパフォーマンスが落ちる為:
/* NG */ * { margin: 0; padding: 0; }
最優先セレクタ ( !important
)は使用してはならない。強制的に優先度を決めると他のものとの優先度の比較が難しくなる為:
/* NG */ .message { margin-bottom: 20px !important; }
タイプセレクタは使用してはならない。パフォーマンスの低下につながる為:
/* NG */ p.message { margin-bottom: 20px; } /* OK */ .message { margin-bottom: 20px; }
ショートハンドプロパティ
可能な限り使わない。指定が読み取りにくいことや余計な打ち消しをすることがある為。
例外として margin
や padding
で複数箇所の指定をするとき、border
などの単純な指定をするときはショートハンドを使う。
/* NG */ .body { margin: 0 20px 0 0; padding: 0 0 20px; background: red url(...) repeat-x 0 0; font: italic lighter 14px/1.4 Georgia, serif; } /* OK */ .body { margin-right: 20px; padding-bottom: 20px; background-color: red; background-image: url(...); background-repeat: repeat-x; background-position: 0 0; font-familiy: Georgia, serif; font-style: italic; font-weight: bold; font-size: 14px; line-height: 1.4; } /* Exception */ .module-bordered { margin: 0 auto; padding: 20px 0; border: 1px solid ##ccc; }
ネストの上限
ネストは3階層以下に収める:
/* OK: 最大深度 */ .outer { background-color: red; } .outer .inner { position: relative; margin: 0 auto; width: 300px; } .outer .inner:before { content: "ribbon"; position: absolute; top: 10px; left: -10px; } .outer .inner .box-left { float: left; width: 100px; } .outer .inner .box-right { float: right; width: 100px; }
CSS ハック
使ってはいけない。
余計なモジュールの構造化は避ける
余計なモジュール化は避けよう。 親要素に子要素が紐付いているリストやテーブルには、子要素に対してモジュール構造を持たせる必要はない。
<!-- NG --> <style> .list { ... } .list-item { ... } </style> <ul class="list"> <li class="list-item"> ... </li> <li class="list-item"> ... </li> <li class="list-item"> ... </li> </ul> <style> .table { ... } .table-row { ... } .table-header { ... } .table-data { ... } </style> <table class="table"> <tr class="table-row"> <th class="table-header"> ... </th> <td class="table-data"> ... </td> </tr> </table> <!-- OK --> <style> .list { ... } .list li { ... } </style> <ul class="list"> <li> ... </li> <li> ... </li> <li> ... </li> </ul> <style> .table { ... } .table tr { ... } .table th { ... } .table td { ... } </style> <table class="table"> <tr> <th> ... </th> <td> ... </td> </tr> </table>