概要
最近バックエンドからフロントエンドになり、「CSSアーキテクチャについてお勉強してみよう!」ということで、一旦代表的なものをまとめてみました。
CSSアーキテクチャとは
- cssの設計方法
- 命名規則やディレクトリ構成や色々ある
- 汎用性を持たせる設計をするために、誰がみても、途中で誰が入っても構成等がわかるように設計しようねという思想からきてるっぽい
BEM
コンセプト
- CSSセレクタの命名規則と言われている
- Block,Element,Modifierの略
- Block:塊
- ヘッダー、ナビゲーション、フッターなどのパーツ
- 独立してる
- Element:要素
- 検索ボタン、検索ボックスなどの部品
- 機能を持っている
- Modifier:装飾
- 部品の状態の色等の装飾
- Block:塊
実例
命名規則
-
block
に対して、element
とmodifier
をそれぞれ_(アンダースコア1つ)
・__(アンダースコア2つ)
・-(ハイフン1つ)
で繋げてセレクタを作る -
--(ハイフン2つ)
で繋ぐmindBEMding
という書き方もある -
これらを「セパレーター」と呼ぶ
- セパレーターを使い分けることで、BlockとElementの区切りなのか、Modifierの区切りなのか、それとも...といった判別ができるようになる
- BlockとElementの区切りは
__(アンダースコア2つ)
- Modifierの区切りは
_(アンダースコア1つ)
- 単語の区切りは
-(ハイフン1つ)
etc...
- BlockとElementの区切りは
- セパレーターを使い分けることで、BlockとElementの区切りなのか、Modifierの区切りなのか、それとも...といった判別ができるようになる
-
例:ブロックの中に3つのボタンがあり、真ん中のボタンだけを赤くする場合
test.html<div class="test"> <button class="test__button">テスト</button> <button class="test__button_red"テスト赤色</button> <button class="test__button">テスト</button> </div>
style.css.test { border: 1px solid #ccc; padding: 16px; text-align: center; background-color: #fafafa; } .test__button { width: 200px; padding: 8px 0; border: 1px solid #ccc; } .test__button_red { background-color: red; }
メリット
- 基礎知識があれば、途中で入った人もCSS設計を理解しやすくすぐに作業ができる
- 多くの人が関わり、長期で運用される・メンテナンスが繰り返されるプロジェクト向き
- 汎用性・流用性の高いものができるので、誰でもメンテナンスがしやすい
- コミュニケーションが取りやすい
デメリット
- class名が冗長になる
- Elementのclass名にはblock名を含める必要がある等
- セパレーターの使い方を統一してないと死ぬ
SMACSS
コンセプト
- Sassを利用することを前提とし、ファイルをモジュールやレイアウトごとに細分化した後にすべてstyle.scssに@importしてコンパイルすることを推奨している
- CSSを以下5つに分割する考え方
- ベース
- 要素セレクタ・属性セレクタ・擬似セレクタなど
-
body
・a
・input
等...
-
- 要素セレクタ・属性セレクタ・擬似セレクタなど
- レイアウト
- 構成の大枠のものを定義する
- 例:ヘッダー、フッター、サイドバー等
- 接頭辞に
.l-
・.la-
をつける
- 構成の大枠のものを定義する
- モジュール
- ページを構成するもの全て
- 部品ごとのスタイルの指定をする
- 例:
.logo
・.tabs
・.box
・.list
等
- 例:
- 接頭辞はつけない
- ステート
- javascriptで状態を変化させるときのパターン分け
- クリックしたらどうなるとか
- クラス名の接頭辞に
is
をつける
- javascriptで状態を変化させるときのパターン分け
- テーマ
- テーマの切り替えに関すること
- bodyに対してテーマ用のクラスを用意する ### 実例
- ベース
ディレクトリ構成例
├── style.scss
│
├── base //ベースに関すること
│ ├── _base.scss
│ └── _mixins.scss
│
├── layout //レイアウトに関すること
│ ├── _top.scss
│ ├── _header.scss
│ └── _footer.scss
│
└── module //モジュールに関すること
├── _btn.scss
├── _logo.scss
└── _nav.scsss
コード
_top.scss
.l-test {
width: 500px;
height: 100px;
}
メリット
- 1ファイルのコード量が少なくなる
- 接頭辞をつけることで何の要素なのか、どこの要素なのかが分かりやすい
- 役割ごとに分けることで、コードの混在を防ぐことができる
デメリット
- Sass使わない場合はあまり意味をもたないかもしれない...
- ディレクトリの中にあるファイルが多くなる
OOCSS
コンセプト
- オブジェクト指向を取り入れる
- 構造(形をつくるもの)とスキン(見た目)を分けましょうという考え
- 構造
-
width
・height
・border
等
-
- スキン
-
color
・border-color
・background-color
等
-
- 構造
実例
アンチパターン
- 同じプロパティ・値を繰り返し書く
- 構造に関することと見た目に関することを混在して記述
test.html <div class="box1"> <p>赤色を背景にするよ</p> </div> <div class="box2"> <p>青色を背景にするよ</p> </div>
.box1 {
float: left;
width: 350px;
background-color: blue;
color: white;
text-align: center;
}
.box2 {
float: left;
width: 350px;
background-color: blue;
color: white;
text-align: center;
}
推奨される書き方
- 共通のクラス名とそれとは別のクラス名を用意する
- 共通のクラスには構造を、別のクラスにはスキンに関することを記述する
test.html
<div class="box red-box">
<p>赤色を背景にするよ</p>
</div>
<div class="box blue-box">
<p>青色を背景にするよ</p>
</div>
style.css
.box { //構造に関すること
float: left;
width: 350px;
text-align: center;
background-color: white; // デフォルト値
color: black; // デフォルト値
}
.red-box { //見た目に関すること
background-color: blue;
color: white;
}
.blue-box { //見た目に関すること
background-color: red;
color: white;
}
メリット
- 繰り返し同じプロパティ・値を書かないので修正が入った場合、修正箇所を少なくすることができる
- 共通化することでCSSのコードの量を減らすことができる
デメリット
- コードが複雑になる
- 設計思想を理解するのに時間がかかる
ECSS
コンセプト
- OOCSSが繰り返しを許容しないのに対し、ECSSは繰り返しを許容し、適切に分離することを目指す
- 一番大きいものを探して、その中にどんな要素が必要なのか考える
- 特定のスコープで分解する
- 命名規則はBEMの恩恵を受けている
- 名前空間
- 接頭辞でコンテキスト・モジュールを表す
- モジュール
- BEMでいう
Block
- 上位のDOM
- BEMでいう
- コンポーネント
- BEMでいう
Block
- 親のDOMに内包される要素
- BEMでいう
- 子ノード
- BEMでいう
Element
- BEMでいう
- バリアント
- BEMでいう
Modifier
- BEMでいう
- 名前空間
実例
命名規則
- 名前空間に
-(ハイフン1つ)
を足して、接頭辞として使う - 名前空間とバリアントはローワーキャメルケース
-
namespace
・variant
-
- 上記以外はアッパーキャメルケース
-
ModuleName
・ChildNode
-
全て書くと以下のような形
namespace-ModuleName_ChildNode-variant
namespace-ComponentName_ChildNode-variant
ディレクトリ構成
- コンテキストをスコープとしてファイルを管理する
- cssとjsを並列に管理することを推奨
- Namesapce毎にアセットを分けて管理する
例
├── Top //Namespace
│ ├── css
│ ├── js
│ └── img
├── Page2 //Namespace
│ ├── css
│ ├── js
│ └── img
├── Page3 //Namespace
│ ├── css
│ ├── js
│ └── img
└── Page4 //Namespace
├── css
├── js
└── img
メリット
- Namespaceごとに管理できるので、不要になったときに消しやすいし、必要になったときに追加しやすい。
- 新規ページで似たようなページを作る際既存のページに影響が出づらい
デメリット
- 同じCSSをひたすら量産し続けるので、ファイル量が膨大になる
Atomic Design(おまけ)
- ⚠️コメントでも頂いておりますが、Atomic DesignはCSSアーキテクチャではありません。この記事を書くときに筆者の理解が浅くココに記載してしまいました。申し訳ございません。⚠️
コンセプト
- ページ単位ではなく、コンポーネント単位でデザインカンプを作る考え方
- コンポーネント同士の組み合わせでページを作る
- 小さいものから少しずつ大きく
- コンポーネントは以下の5つからなる
- 原子(Atoms)
- それ以上分割できない要素の単位
- 例:入力フォーム・ボタンなど
- それ以上分割できない要素の単位
- 分子(Molecules)
- 原子を2つ以上組み合わせたもの
- 例:検索フォーム(入力フォーム + 検索ボタン)
- 原子を2つ以上組み合わせたもの
- 有機体(Organisms)
- 複数の分子を組み合わせたもの
- 例:ヘッダー・フッターなど
- 複数の分子を組み合わせたもの
- テンプレート(Templates)
- 有機体を組み合わせたもの
- 画像や文言等のデータが入っていない
- 例:ワイヤーフレーム
- ページ(Pages)
- テンプレートに画像や文言等のデータを入れたもの ### 実例
- 原子(Atoms)
- Abema TV
- 以下URL15ページ目から Atomic Design powered by React @ AbemaTV
メリット
- 最小単位まで細分化されているので、修正をしやすい
- 共通化しているので、デザイン変更に対応しやすくなる
- シンプルな構造になっているので、デザインが統一されやすい
デメリット
- 既存のページが細分化されていなかった場合にAtomic designを途中から導入するにはコストがかかる
参考資料
CSSを長生きさせるための設計手法まとめ(*ECSSあり)
SMACSSによるCSSの設計第1回 ベースとレイアウト
知っておきたいHTMLテンプレート設計法第1回 OOCSSの基本
BEMによるフロントエンドの設計第1回 基本概念とルール
それぞれの設計思想やコード例が端的にわかりやすく説明されていて参考になります
少し気になったこととして、Atomic Designはより大局的な話題で、CSSアーキテクチャではない気がします。
この記事でも言及されているように、デザインカンプを作る工程あたりの実装以前から始まるレイヤーの話で
コンポーネントの分割・結合単位については言及していますが、CSS上の規約・構成やコンポーネントをどのように実装するかについては言及されていません。
コンポーネントはBEMやOOCSSなどを別途採択して実装する必要があるところが、Atomic DesignはCSSアーキテクチャではないと思うところです。
@Ragg様
コメントありがとうございます!
理解が不足したまま記事を投稿して大変申し訳ございませんでした。
確かにおっしゃる通り、Atomic DesignはCSSアーキテクチャではないですね。ここの理解が曖昧でしたので、コメントで詳細に説明いただき、非常に嬉しいです!