良い感じにCSS書くために"rscss"という考え方がちょうど良かったので訳しつつまとめとく
BEMやらSMACSSやら、CSS設計のアイディアは色々あるのだけど、どうにも複雑で。。
そんなときにrscss(Reasonable System for CSS)を見つけたんだけど、これがちょうどいい感じで、縛りもきつくなくて導入しやすかった。
ので、改めてドキュメントを訳しつつ、まとめておく。
Introduction
1000行を超えるようなCSSはすぐに手に負えなくなる。
- このクラスは何を意味するのだろう
- このクラスはまだ使用されているのだろうか
- このクラスは使ってよいのだろうか、衝突しないか
rscssはこれらを把握するための試みであり、フレームワークではなく、保守性の高いCSSを構築するためのアイディアセットである。
Components
それぞれのUIのパーツをComponentとして捉えて名前付けしていく。
このとき、最低2単語で単語間は -
でつなげるケバブケースで名前付けする。
.like-button { /* ... */ } .search-form { /* ... */ }
Elements
ElementsはComponentの中のもの。
例えば検索フォームなら、テキストフィールドとサブミットボタンで構成されるので
.search-form { > .field { /* ... */ } > .action { /* ... */ } }
セレクタには可能な限り >
をつけるようにする。
もし、名前が2単語以上になりそうなら、何も挟まずに連結させる。
.profile-box { > .firstname { /* ... */ } > .lastname { /* ... */ } > .avatar { /* ... */ } }
また、タグをセレクタとするのは避ける。
.article-card { > h3 { /* 避ける */ } > .name { /* 可能な限りclass名で */ } }
Variants
Variantsは「別形」とか「変種」とかいう意味。
ComponentsやElementsに持たせることで、状態や見た目を変える。
.like-button { &.-wide { /* 大きめ */ } &.-short { /* 小さめ */ } &.-disabled { /* 押せない */ } }
接頭辞に -
をつけて、曖昧さをなくすようにする。
Componentsのネスト
ある程度の規模ならComponentをネストする必要も当然でてくる。
このとき、例えば、別のComponentに何かしらの方法(JSによる動的なDOM要素追加とか、だろうか)でComponentをネストするとき、Componentのクラス名によるセレクタのネストは避けるべき。
.article-header { > .vote-box > .up { /* これは避ける */ } }
代わりに、そのときVariantも追加して、
<div class='article-header'> <div class='vote-box -highlight'> ... </div> ... </div>
外側のComponentから追加したVariantに対して適用していくようにする。
.vote-box { &.-highlight > .up { /* ... */ } }
また、こんな感じでコードが汚くなってきたら
<div class='search-form'> <input class='input' type='text'> <button class='search-button -red -large'></button> </div>
クラス名を置き換えて
<div class='search-form'> <input class='input' type='text'> <button class='submit'></button> </div>
@extend
などを使ってシンプルにするのも手。
.search-form { > .submit { @extend .search-button; @extend .search-button.-red; @extend .search-button.-large; } }
Layout
Componentは再利用されるべきなので、位置に関するプロパティをComponentに記述するのは避ける。
例えば以下のようなもの。
top
やleft
float
margin
width
やheight
ただ、アバターやロゴのような幅や高さが固定されるものについては例外。
もし、Componentに対してこれらを定義したいなら、以下のようにコンテキストに基づいて定義していく(.article-card
に対して定義するのではなく .article-list
の中の .article-card
に対して定義する)。
.article-list { & { @include clearfix; } > .article-card { width: 33.3%; float: left; } } .article-card { & { /* ... */ } > .image { /* ... */ } > .title { /* ... */ } > .category { /* ... */ } }
Helpers
Helpersという汎用クラスを別ファイルにまとめて用意しても良い。
接頭辞は _
。
使いすぎ注意。ご利用は計画的に。
._unmargin { margin: 0 !important; } ._center { text-align: center !important; } ._pull-left { float: left !important; } ._pull-right { float: right !important; }
CSS structure
1つのファイルに1つのコンポーネントとする。
/* css/components/search-form.scss */ .search-form { > .button { /* ... */ } > .field { /* ... */ } > .label { /* ... */ } // variants &.-small { /* ... */ } &.-wide { /* ... */ } }
あと、過剰なネストはすぐにワケワカランことになるのでやめよう。
/* 3階層のネストは行き過ぎ */ .image-frame { > .description { /* ... */ > .icon { /* ... */ } } } /* 2階層にとどめよう */ .image-frame { > .description { /* ... */ } > .description > .icon { /* ... */ } }
Pitfalls
Pitfallsって落とし穴って意味なのか。
Elementsの命名がかぶっちゃう場合もあるので注意。
<article class='article-link'> <div class='vote-box'> <button class='up'></button> <button class='down'></button> <span class='count'>4</span> </div> <h3 class='title'>Article title</h3> <p class='count'>3 votes</p> </article>
こんなときのために >
を使っておくと、特定のComponentのElementにだけ適用できるはずなので、極力 >
は使うべし。
Apprehensions
-
使いたくない場合は使わなくても良い。
でも、Components、Elements、Variantsの考え方は外さないように。
もしComponentsの2単語が思い浮かばないなら、接尾辞をつけてブロック要素なのかインライン要素なのかを明確にするとよい。
- .alert-box
- .alert-block
- .link-button
- .link-span
Other resources
割愛。。
Summary
まとめ。
- Componentsで考える。命名は2単語で
-
区切り。 - ComponentsはElementsを持つ。命名は1単語。
- 状態はVariantsで表す。接頭辞に
-
をつける。 - Componentsはネスト可。
- シンプルにするために拡張しても良いということを忘れずに。