ホーム
企業情報
テックレポート - TechReport
テックレポート詳細
テックレポート - TechReport
メンテナブルCSS
執筆者
- 執筆者:
- 中島幸樹
- 所属部署:
- 新課金事業部(福岡)
- 業務経歴:
- 元組み込みプログラマ。Android/iOSアプリの開発経験を経て、現在はWebのフロントエンド開発に従事。
目次
- 目次
- 概要
- 1.序論
- 2.CSSルール
- 2-1.可能な限り短いクラス名にする。 ただし意味が分からないほどには省略しないこと
- 2-2.可能な限り短いプロパティで定義すること
- 2-3.ゼロ以下の小数には接頭の0を省く
- 2-4.色定義は出来る限り三桁で記述する
- 2-5.クラス名の単語はハイフンで繋ぐ
- 2-6.IDセレクタは使わない
- 2-7."js-"プレフィックスを付けたクラスをCSSに定義しない
- 2-8.状態を示すクラス名には".is-"プレフィックスを付ける
- 2-9.クラスにはタイプセレクタを記述しない
- 2-10.ユニバーサルセレクタは使用しない
- 2-11.プロパティは常に同じ順序で並べる
- 2-12.数値ゼロには単位をつけない
- 2-13.プロパティ定義は一定のルールで記述する
- 2-14.ブロックの開始位置を統一する
- 2-15.インデントのコードを統一する
- 2-16.コメントスタイルを統一する
- 3.CSSツール
- 4.まとめ
- 5.参考文献
概要
メンテナブルなCSSを目指し、定義された一般的なCSSルールの紹介と、それらのルールを適用するにあたって活用できるツールを報告します。
1. 序論
CSSは記述ルールが簡素であり、少しの学習コストですぐに記述ができる手軽なツールです。
しかし、大規模なアプリケーションで複数人で開発するケース等では、見栄えだけしか考えずに身勝手にコーディングしてしまうと、
非常にメンテナンスコストがかかる負の遺産が作られてしまいます。
そのためCSSの品質を保つために様々なプロジェクトで、CSSの定義ルールが決められています。
本稿では一般的なCSSの定義ルールと、そのルールがなぜ作られたのかを合せて報告致します。
また、CSSのルールを適用するにあたって、手動・目視でルールの適用をチェックするのは非常にコストが高い作業です。
これらルールの適用を補助するツール群を、合せて報告致します。
2.CSSルール
2-1.可能な限り短いクラス名にする。ただし意味が分からないほどには省略しないこと
一般的な単語として省略できるものは極力短いクラス名で書く。ただし、分からないほど短いクラス名にはしないこと。
navigation { |
#nav { |
なぜこのルールがあるの?
ファイルサイズ節約のため。
クラス名が無駄に長い=ファイルサイズが大きくなる=ユーザのもっさり体験に繋がるのが主な理由と思います。
ただし、意味が分からないほどに省略してしまっては、メンテナンスが出来ません。あくまで無駄に長いクラス名にはしない、一般的に意味がわかる単語は省略形で書くというルールを守れば良いのではないでしょうか。
2-2.可能な限り短いプロパティで定義すること
borderやmargin等のプロパティはtop/bottom/left/right等に分割して書くことができますが、出来る限りまとめて定義する。
.list-box { |
.list-box { |
なぜこのルールがあるの?
ファイルサイズ節約のため。
2-3.ゼロ以下の小数には接頭の0を省く
ゼロ以下の小数を指定する場合、接頭の0は省く。
font-size: 0.8em; |
font-size: .8em; |
なぜこのルールがあるの?
ファイルサイズ節約のため。
2-4.色定義は出来る限り三桁で記述する
16進数で色を定義する場合、同値が続く場合は出来る限り省略する。
color: #eebbcc; |
color: #ebc; |
なぜこのルールがあるの?
ファイルサイズ節約のため。
2-5.クラス名の単語はハイフンで繋ぐ
クラス名の単語区切りにはハイフンを入れる
maintitle { |
main-title { |
なぜこのルールがあるの?
諸説ありますが、
- 昔のブラウザはCSSセレクタにアンダースコアを許可してなかった
- 単純にアンダースコアよりもハイフンのほうが読みやすい(英語圏)
- JavaScriptの変数の命名規則と矛盾させることで、区別しやすくなる という意見があります。
2-6.IDセレクタは使わない
CSS定義には、IDセレクタ(#sample)は使用しない
#info-title { |
.info-title { |
なぜこのルールがあるの?
大変議論になるところだと思います。
理由1: ID要素は再利用可能でない
ID要素はページ上に1つのインスタンスしか存在せず再利用できないため、個別のCSS定義を作成するのは非効率的です(理由3に続く)
理由2: スタイル適用の優先順位を意識する必要がある
一般的なCSSの定義方法
- スタイルは上から順に定義されて、以前のルールを上書きしていく
- 順番とは別に個別に定義したい場合は、加重セレクタを使って重み付けをするが一般的と思います。
IDセレクタはclassセレクタよりも優先されるためこれらのルールとは別で判断しなければならず、CSSファイルの可読性が落ちてしまいます。
理由3: IDは特定の何かを挿しているため、抽象化することは厳しい
理由1ともかぶっているのですが、cssはできるだけ共通化してシンプルでスマートな方がいいです。
クラス定義の場合は.common-sectionのように抽象化して意味付けをすることで、より汎用的なスタイルが定義できます。
IDを使ってしまうと絶対に1つしか存在しない意味になってしまうので、#qa-section-for-johnのように特定の何かに限定してしまい、抽象化することには向いていません。
省力化して共通に使用するのであれば、class定義にするべきです。
IDを使用してピックアップしても、他のセレクタを追加することでパフォーマンスが否定されてしまう
#profile-module {…} |
上記に対する反論:だってIDセレクタの方がクラスセレクタより高速でしょ?
確かにそうですが、気にするほど高速にはなりません。あっても数百マイクロ秒の差では、むしろ本当に計測できているかさえ怪しんでしまうレベルです。
HTML内の不要な改行コードを消したりminify/concatした方がまだ高速化になると思います。
こんな努力をする暇があるなら、セレクタ名がよりセマンティックで明瞭になるように考えることに時間を使って、メンテナンス性を向上させましょう。
ID要素の使用はJavaScriptに限定し、CSSではクラス要素を使うべきです。
2-7."js-"プレフィックスを付けたクラスをCSSに定義しない
これは、JavaScriptから要素を参照するためだけに定義されたクラス名に、".js-"プレフィックスを付けるというルールに基づいています。
そのため、".js-"プレフィックスを付けたクラス定義は存在するはずがありません。
.js-comment-button { |
.comment-button { |
なぜこのルールがあるの?
JavaScriptとCSS、それぞれの修正が極力相手に影響しないよう、疎結合を保つため。
2-8.状態を示すクラス名には".is-"プレフィックスを付ける
状態を意味するクラス名には、".is-"プレフィックスを付ける
.withdrawal { |
.is-withdrawal { |
なぜこのルールがあるの?
可読性向上のため。
他のクラスと組み合わせて状態を示す場合に、それが一目で明確になります。
2-9.クラスにはタイプセレクタを記述しない
li.member-list { |
.member-list { |
なぜこのルールがあるの?
可読性向上とファイルサイズ節約のため。
2-10.ユニバーサルセレクタは使用しない
* { |
html,body { |
なぜこのルールがあるの?
可読性向上のため。
2-11.プロパティは常に同じ順序で並べる
- 1.位置情報系(position, top, right, z-index, display, float等)
- 2.サイズ(width, height, padding, margin)
- 3.文字系(font, line-height, letter-spacing, color- text-align等)
- 4.背景(background, border等)
- 5.その他(animation, transition等)
.example { |
.example { |
なぜこのルールがあるの?
可読性向上のため。
ただし、慣れないと意外と面倒…。
2-12.数値ゼロには単位をつけない
プロパティの値として0を指定する場合は、単位表示は省略する
.example { |
.example { |
なぜこのルールがあるの?
JavaScriptとCSS、それぞれの修正が極力相手に影響しないよう、疎結合を保つため。
2-13.プロパティ定義は一定のルールで記述する
- ・ブロック単位でインデントを付ける
- ・プロパティの終端には必ず;を付ける
- ・コロンの後には必ず半角スペースを入れる
- ・別々のセレクタとプロパティは複数行に書く
- ・別々のCSSルールは1行空けて書く
.friend-header {margin: 0;padding:1em 2em} |
.friend-header { |
なぜこのルールがあるの?
可読性向上のため。
2-14.ブロックの開始位置を統一する
"{"の位置は、セレクタと同じ行か一段落とすか統一する。
.sample { |
.sample { |
なぜこのルールがあるの?
可読性向上のため。
どちらのほうが読みやすいかは、フロント開発者の経験によって変わるとは思います。
混在すると著しく読みづらいため、話し合って決めると良いんじゃないでしょうか。
2-15.インデントのコードを統一する
インデントをソフトタブ(2スペース or 4スペース)にするか、ハードタブ(\t)にするか統一する。
.data-unit { |
.data-unit { |
なぜこのルールがあるの?
可読性向上のため。
どちらのほうが入力しやすいかは、フロント開発者の経験によって変わるとは思います。
混在すると著しく読みづらいため、話し合って決めると良いんじゃないでしょうか。
2-16.コメントスタイルを統一する
//ベースのコメントにするか、/**/ベースのコメントにするか統一する。
(※LESSやSass等のCSSプリプロセッサを導入する前提です)
// 友達の名前 |
// 友達の名前 |
なぜこのルールがあるの?
可読性向上のため。
どちらのほうが入力しやすいかは、フロント開発者の経験によって変わるとは思います。
混在すると著しく読みづらいため、話し合って決めると良いんじゃないでしょうか。
ただし、styledoccoを使うなら/**/を使った方が良いです。
3.CSSツール
3-1.CSS Validator
http://jigsaw.w3.org/css-validator/
みなさんおなじみのW3C公式のCSS構文チェックツール
3-2.PrettyCSS
https://github.com/fidian/prettycss/
nodeで動作するCSSパーサー。lintツールやエラーチェッカ等の機能もある。
3-3.CSScomb
CSSプロパティの並びを整列させるツール。がぜん読みやすくなる
3-4.RECESS
https://github.com/twitter/recess
Twitter製のLESSコンパイラ。実は豊富なCSSルールチェック機能が付属しています。
4.まとめ
個人的な反省として、とにかく早く実装しようとして後先かまわずCSSを定義してしまっておりました。
しかしそれは眼前のゴールに向けて楽をするために、借金をして負債を積み重ねているだけでした。
開発・運用を通じてプロジェクトが大きなゴールにたどり着くための最短経路として、
やはり品質の高いCSSを作り続ける必要があると確信しています。
CSSルールを守ってメンテナブルCSSを守りつつ、作業コストを削減するためにツールを活用する。
楽していいものつくりましょうぜ。
5.参考文献
http://google-styleguide.googlecode.com/svn/trunk/htmlcssguide.xml
https://github.com/twitter/recess
http://screwlewse.com/2010/07/dont-use-id-selectors-in-css/
http://os0x.hatenablog.com/entry/20100518/1274204934
http://enja.studiomohawk.com/2013/03/24/code-smells-in-css/
https://github.com/styleguide/css
https://github.com/necolas/idiomatic-css
http://csswizardry.com/2012/04/my-html-css-coding-style/