CSS 設計でいう保守性とは、新しいルールの追加・更新のしやすさ をあらわす。保守性を高めるためには、変更の局所化、他のルールへの副作用を最小にするアーキテクチャ を採用します。
CSS 設計
- 設計思想は FLOCSS ベースの ECSS + rscss + Tailwind CSS のいいとこ取り
- 命名規則は MindBEMding (以降、BEM)
- 開発言語は Sass + PostCSS
コンポーネント粒度
FLOCSS ではプロジェクトにおいて繰り返されるビジュアルパターンをすべて Object として定義します。Object には、Component と Project のレイヤーがあり、この 2 つの判別において Atomic Design のコンポーネント粒度の考えを拝借します。具体的には、
- Component:Atoms
- Project:Molecules
に分類します。
単語間の区切りにダッシュやアンダースコアを使わない
BEM や接頭辞の命名規則の混在を防ぐため、単語間の区切りにダッシュやアンダースコアを使いません。個人的にキャメルケースではなく、 すべて小文字の命名を推奨 します。プログラミング言語は、一定の記法(e.g. キャメルケース、スネークケース)に従うことが重要になります。逸脱した命名は、読み手の認知コストが上がり、可読性が損なわれます。HTML の複合語はすべて小文字になっている記法(e.g. <textarea>
, maxlength
属性)に従います。
略語は原則禁止
原則、単語の省略形を禁止します。特にプロジェクト固有の省略形は、極力避けるべきです。
名前空間の活用
クラス名の衝突や BEM の Block の肥大化を防ぐため、プロジェクトやページ固有の 名前空間(namespace) をつけることを推奨します。
接頭辞で役割を明確にする
Component や Project レイヤーの責務を明確にするため、クラス名の接頭辞は有効です。ただし、clearfix
のようなクラス名から責務を判断できる場合、必ずしも接頭辞をつける必要はありません。
JavaScript フック
単一責任の原則より、同一クラスに CSS と JavaScript の両方でバインドしません。JavaScript でバインドする固有クラスを作成し、接頭辞 js-
をつけましょう。
variant(2020/9/11 更新)
メディアクエリの範囲特性を満たすスタイルを適用するユーティリティクラスにはブレークポイントの接頭辞(e.g. sm:
, md:
)をつけます。CSS のセレクタに :
を使用する場合、\
でエスケープしてください。
.sm\:text-align-center {...}
Layout レイヤーの ID セレクタは禁止
FLOCSS の Layout レイヤーは ID セレクタの使用を許可していますが、詳細度の高い ID セレクタを抽象的な Layout レイヤーに使えば、Component や Project レイヤーのオーバーライドが困難になります。詳しくは、カスケーディングと詳細度|FLOCSS を参照ください。
独自の BEM 記法
- Element はアンスコひとつ
- Modifier はハイフン始まり
※ハイフンの後に数字で始まるセレクタは不正になるため注意しましょう。
<!-- Element の記法 -->
<div class="block_element"></div>
<!-- Modifier の記法 -->
<div class="block -modifier"></div>
Dash prefix の注意点
ハイフンひとつの接頭辞(Dash prefix)は、BEM の冗長性をなくし、そのクラスが Modifier だと認識しやすい点に優れています。その反面、BEM の明確性が失われます。HTML 要素に複数の Block や Element がある場合、Modifier がどれに依存しているのか判断しづらくなります。
<div class="block block_element -modifier"></div>
Element の入れ子は割れた窓
HTML の入れ子構造を反映させたクラス名は 非推奨(BEM の公式ドキュメントも非推奨) です。HTML の構造に依存したクラス名は、HTML の変更と、それに伴う CSS の修正が必要になります。
.block_element1_element2 {...}
.block_element2 {...}
単独で Modifier を宣言しない
Modifier は Block、または、Element のマルチクラスで宣言しましょう。マルチクラス設計は詳細度を高くしますが、記述順に依存しないスタイルの上書き ができます。また、Dash prefix を採用した Modifier の場合、グローバルに影響を与えにくいメリットがあります。
.-modifier {...}
.block {
&.-modifier {...}
}
class 属性値の記述順
class 属性値に指定するクラス名の順番を スタイルが上書きされる順 にしましょう。左側は「抽象的 / 詳細度低」となるクラスを、右側は「具体的 / 詳細度高」クラスの順で指定しましょう。
<div class="c-component p-project -modifier"></div>
状態は WAI-ARIA で制御する
DOM の状態変化を伝えるために WAI-ARIA で制御することを推奨 します。 .is-*
のクラスを追加するよりも 名前のバラつきが起こりにくい、標準化された支援技術によってアクセシブルになる ことが期待できます。
<div class="block is-selected"></div>
<div class="block" aria-selected="true"></div>
!important
は絶対悪でない
!important
は、詳細度の調和を壊す存在であり、基本的に使うべきルールではありません。ただし、僅かなスタイル調整の Utility には !important
の使用を推奨 します。これは、確実なスタイルの適用を開発者が期待しているため、!important
の許容範囲になります。
アンパサンドの多用に注意!
BEM の明確性が失われる、セレクタ検索が困難になる という理由により Block を &
で省略しません。
.block {
&_element {...}
}
.block_element {...}
Utility からヘルパークラスを切り離す
FLOCSS の Utility は、僅かなスタイル調整のための便利クラスと clearfix のようなヘルパークラスを定義します。この二つのクラスを分けて管理します。
複数の import は glob 形式で読み込ませる
Sass の機能である Partials は、レイヤー毎にファイルを分割する FLOCSS の考えと相性がよいです。加えて、glob 1 を使った import にすれば拡張性に優れます。ただし、現在(2019/08/11 執筆時点)の Sass の標準機能では glob をサポートしていないためプラグインが必要です。
@import "_partials/components/**";
-
glob とは、ワイルドカード(
*
)でファイル名を特定するパターンである。 ↩