この記事は、現在僕が携わっているひだまりプロジェクト (仮称) で使用している CSS 設計ルールについてまとめたものです。
ベースとなる CSS 設計
-
BEM (MindBEMding)
- BEM 自体についての説明は省略します。
- 一部 SMACSS を参考にした独自ルールを取り入れています。詳しくは後述します。
ルール
(1) Element をネストしない
BEM を使用する際の大原則として block__element
という対応関係を厳守します。
NG
category__item__name
は block__element1__element2
と Element がネストしています。
<head>
<style>
.category-list {}
.category-list__item {}
.category-list__item__name {}
</style>
</head>
<body>
<div class="category-list">
<div class="category__item">
<span class="category__item__name"></span>
</div>
</div>
</body>
OK
category-list__item
の item
は category-list
という Block の Element である一方で、
name
という Element を持った category-item
という Block でもあるとみなします。
<head>
<style>
.category-list {}
.category-list__item {}
.category-item {}
.category-item__name {}
</style>
</head>
<body>
<div class="category-list">
<div class="category__item category-item">
<span class="category-item__name"></span>
</div>
</div>
</body>
(2) Modifier の代わりに SMACSS の State を使う
ひだまりプロジェクトの独自ルールとして、BEM の Modifier の代わりに SMACSS の State ルールを使うようにしています。
State ルールでは is-
あるいは has-
というプレフィックス付きのクラスを使用します。本ルールではこれを Modifier 付きのクラスの代わりに使用します。
このルールを用いることで、Modifier を用いる際にセレクタ記述が冗長になってしまうのを防ぐことができます。
これは JavaScript (jQuery) でクラスを追加したり削除する場合にも都合がいいです。
NG
HTML
<head>
<style>
.category-item {}
.category-item--focused {}
</style>
</head>
<body>
<div class="category-item category-item--focused">
<span class="category-item__name"></span>
</div>
</body>
JavaScript
var block = 'category-item';
$('.' + block).addClass(block + '--focused');
OK
HTML
<head>
<style>
.category-item {}
.category-item.is-focused {}
</style>
</head>
<body>
<div class="category-item is-focused">
<span class="category-item__name"></span>
</div>
</body>
JavaScript
$('.category-item').addClass('is-focused');
(3) 原則としてセレクタをネストしない
原則としてセレクタをネストしてはいけません。それぞれのセレクタを独立させます。
Sass を使用する場合も、CSS にコンパイルした後でセレクタがネストしないようします。
具体的には &
(Referencing Parent Selectors) を使用します。
NG
Sass
.category-list {
.category-list__item {}
}
CSS
.category-list .category-list__item {}
OK
Sass
.category-list {
&__item {}
}
CSS
.category-list {}
.category-list__item {}
(4) Block に State を適用する場合は Element のセレクタをネストする
Block に State ルールを適用し、それが Element にも影響する場合は、ルール (3) の例外としてセレクタをネストさせます。
これは State の指定が冗長になるのを防ぐためです。
ただし、影響範囲が最小となるように、可能であれば子セレクタ >
を使用します。
NG
Sass
.category-item {
&.is-focused {}
&__number {
&.is-focused {}
}
&__name {
&.is-focused {}
}
&__description {
&.is-focused {}
}
}
CSS
.category-item.is-focused {}
.category-item__number.is-focused {}
.category-item__name.is-focused {}
.category-item__description.is-focused {}
OK
Sass
.category-item {
$block: &;
&.is-focused {
// & > &__name
// のように Block の部分に & を使うと、コンパイル後に
// .category-item.is-focused > .category-item.is-focused__number
// と変換されてしまう。
& > #{$block}__number {}
& > #{$block}__name {}
& > #{$block}__description {}
}
}
CSS
.category-item.is-focused {}
.category-item.is-focused > .category-item__number {}
.category-item.is-focused > .category-item__name {}
.category-item.is-focused > .category-item__description {}
参考
- BEMる
- BEM 化されたブログをのぞかせてもらう
-
Using BEM in the Real World: Pitfalls & Advice
- SMACSS の State を使うアイディアは、この記事を参考にしました。