CSS設計の基本：目指すべきCSSと代表的な設計手法

# はじめに
[『Web制作者のためのCSS設計の教科書 モダンWeb開発に欠かせない「修正しやすいCSS」の設計手法』(amazon)](https://www.amazon.co.jp/Web%E5%88%B6%E4%BD%9C%E8%80%85%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AECSS%E8%A8%AD%E8%A8%88%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E3%83%A2%E3%83%80%E3%83%B3Web%E9%96%8B%E7%99%BA%E3%81%AB%E6%AC%A0%E3%81%8B%E3%81%9B%E3%81%AA%E3%81%84%E3%80%8C%E4%BF%AE%E6%AD%A3%E3%81%97%E3%82%84%E3%81%99%E3%81%84CSS%E3%80%8D%E3%81%AE%E8%A8%AD%E8%A8%88%E6%89%8B%E6%B3%95-%E8%B0%B7-%E6%8B%93%E6%A8%B9/dp/4844336355)
を読んで学んだことをまとめます。

普段の業務でCSSを触る時、スタイルの修正という文脈がほとんどであり、CSSを設計という観点から考えることがありませんでした。
しかし、自分が触っているCSSがどのように設計されているかを知らないことで、設計方針から外れた実装をしてしまうということがありました。

本記事では、**良いCSS設計と悪いCSS設計の違い、そもそもCSSの設計にはどのような手法があるのか**という点についてまとめます。



# 目指したいCSSと破綻しやすいCSS
まず、良いCSSと破綻しやすいCSSの違いについてまとめます。

## 良いCSSのゴール
より良い設計のゴールとして、以下の4つが挙げられています。

・予測しやすい
・再利用しやすい
・保守しやすい
・拡張しやすい

### 予測しやすい
期待通りに振る舞うかどうか、ということ。
他のルールが影響して、記述したルール通りの振る舞いや見栄えにならない、または追加したルールが他のルールに影響を与えないようにすること。

### 再利用しやすい
同じスタイルが複数箇所で書かれないようにする。
再利用しやすいルールというのは抽象的で、機能ごとに分離されている必要がある。
遭遇したデザインのマークアップ、CSSを一度作れば、再度同じようなUIに遭遇したときに、わざわざ書き直す必要がないようにするのが理想的。

### 保守しやすい
新しいルールを追加・更新するときに、既存のルールのリファクタリングを必要としないことが大事。
追加したルールによって、既存のルールを壊してしまうことを避けること。

### 拡張しやすい
拡張しやすさというのは、そのCSS設計が、サイトの規模が大きく複雑になるにつれて、拡張しやすいものになっているかということ。
また、そのCSS設計の学習コストが低いこと。

## 破綻しやすいCSS
目指すべきCSSを理解したところで、次に、破綻しやすいCSSについてまとめます。

### HTMLの構造に依存している
HTMLマークアップを使用してCSSスタイルを指定しているとき、そのマークアップが変更された場合、依存しているCSSも変更する必要があります。

### スタイルを取り消している
スタイルの取り消しとは、一度定義したルールを、0やnoneといった値でリセットしていることを指します。
例えば、以下のような下線付きの見出しがあるとします。

```css
.title {
 border-bottom: 2px solid #000;
 margin-bottom: 1em;
 padding: 10em;
 font-size: 24px;
 font-weight: bold;
}
```
これに下線を「取り消す」　ルールが追加された状態が以下です。

```css:CSS
.title {
 border-bottom: 2px solid #000;
 margin-bottom: 1em;
 padding: 10em;
 font-size: 24px
 font-weight bold;
}
.no-border {
 padding-bottom: 0;
 border-bottom: none;
}
```

```HTML:HTML
<h2 class="title no-border">見出し</h2>
```

上記に対し、下線を「追加する」ルールをつくったパターンが以下です。
ルールを書き進める際には、無駄なコードを増やさないために、定義したルールを取り消すのではなく、追加していくのが良いです。

```css:CSS
.title {
 margin-bottom: 0.5em;
 font-size: 2em;
}
.headline {
 padding-bottom: 10px;
 border-bottom: 2px solid #000;
}
```

```HTML:HTML
<h2 class="title headline">見出し</h2>
```

### 絶対値を多用している
絶対値を多用することなく、使用できる場面では相対単位や相対値を使用すべきです。
例えば、font-sizeは親要素のfont-size基準に相対値を設定できたり、line-heightはfont-sizeを基準に値を相対的に設定できたりします。

https://developer.mozilla.org/ja/docs/Web/CSS/font-size#:~:text=%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82-,%3Clength%3E,-%E6%AD%A3%E3%81%AE%20%3Clength

https://developer.mozilla.org/ja/docs/Web/CSS/line-height#number:~:text=%E3%82%92%E4%BD%BF%E3%81%84%E3%81%BE%E3%81%99%E3%80%82-,%3Cnumber%3E%20(%E5%8D%98%E4%BD%8D%E3%81%AA%E3%81%97),-%E4%BD%BF%E7%94%A8%E5%80%A4%E3%81%AF


# CSSにおけるコンポーネント設計
代表的なCSS設計を3つ紹介します。

## OOCSS(Object Oriented CSS、オブジェクト指向CSS)
コンポーネント設計が難しいCSSに対し、オブジェクト指向プログラミングの概念を取り入れ、その実現に近づけたのがOOCSSです。

OOCSSの原則には以下の2つがあります。

**・構造と見た目の分離**
コンポーネントの基本構造と、具体的なルール・機能を分離するということです。

例えば、以下のようなHTML1があったとき、それぞれのスタイルにおいて、アラートメッセージとしてのスタイルは共通です。
そこで、HTML2のようにアラートメッセージというパターンをalertというオブジェクトにします。
これが、構造と見た目の分離です。

```html:HTML1
<div class="success-message">成功のアラートメッセージ</div>
<div class="warning-message">警告のアラートメッセージ</div>
<div class="error-message">エラーのアラートメッセージ</div>
```

```html:HTML2
<div class="alert success">成功のアラートメッセージ</div>
<div class="alert warning">警告のアラートメッセージ</div>
<div class="alert error">エラーのアラートメッセージ</div>
```

**・コンテナーとコンテンツを分離**
「コンテナーとコンテンツを分離」とは、場所に依存しないセレクタを書くということです。
つまり、特定の親要素や階層構造に依存せず、どこに配置しても同じようにスタイルが適用されるセレクタを設計することを指します。

例えば、以下のようなCSSの場合、ヘッダーでしか利用できないロゴのスタイルになってしまいます。

```CSS:CSS
#header .logo {
 display: inline-block;
 width: 200px;
 height: 80px;
}
```

これを .logo という部品として定義することで、ヘッダー以外の箇所でも使用できるようになります。
```CSS:CSS
.logo {
 display: inline-block;
 width: 200px;
 height: 80px;
}
```

## SMACSS(Scalable and Modular Architecture for CSS)
SMACSSはOOCSSをベースに作られた設計です。
SMACSSではCSSを5つのカテゴリに分類し、パターンを抽出しやすくしています。

**・Base**
ブラウザやそのプロジェクトにおける各要素のデフォルトスタイル

**・Layout**
ヘッダー、フッター、コンテンツエリア、サイドバーのような、構成の大枠、セクションを作る要素へのルール

**・Module**
Layoutに該当しない、ページを構成する再利用可能な要素（ボタン、ナビゲーション、リンクなど）

**・State**
JavaScriptによる制御などによって切り替わるような、状態を表すルール

**・Theme**
サイト全体の見た目や雰囲気を設定するスタイル

## BEM（Block Element Modifier）
ページの構成要素を、Block・Element・Modifierに分類して考える設計手法です。
厳格な命名規則が特徴です。

**・Block** 
機能的に独立した再利用可能なコンポーネントです。
Element・Modifierは、このBlockを起点に命名されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3844628/0bd976f3-0f6c-46fc-a213-9aa7ea31b1d7.png)


**・Element**
Blockを構成する要素で、Block外では意味をなさないものです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3844628/5d4ddd97-cc93-424b-ae6a-f23e7be07a9d.png)


**・Modifier**
BlockやЕlementの状態や見た目を変更するもの
以下の例では、Modifierの使用によりメニューブロックの見た目が変わっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3844628/2975365b-3930-44b1-a0ce-d8ca300ef615.png)

### BEMの命名規則
**・Block** 
`.menu`

**・Element**
Blockに対してアンダースコアを2つつける
`.menu__item`

**・Modifier**
BlockやElementに対して、アンダースコア1つ、またはハイフン2つをつける
`menu__item_visible`
`menu__item--visible`


参考：

https://en.bem.info/methodology/key-concepts/


# 最後に
もともとCSS設計という考え方も知りませんでしたが、
[『Web制作者のためのCSS設計の教科書 モダンWeb開発に欠かせない「修正しやすいCSS」の設計手法』](https://www.amazon.co.jp/Web%E5%88%B6%E4%BD%9C%E8%80%85%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AECSS%E8%A8%AD%E8%A8%88%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E3%83%A2%E3%83%80%E3%83%B3Web%E9%96%8B%E7%99%BA%E3%81%AB%E6%AC%A0%E3%81%8B%E3%81%9B%E3%81%AA%E3%81%84%E3%80%8C%E4%BF%AE%E6%AD%A3%E3%81%97%E3%82%84%E3%81%99%E3%81%84CSS%E3%80%8D%E3%81%AE%E8%A8%AD%E8%A8%88%E6%89%8B%E6%B3%95-%E8%B0%B7-%E6%8B%93%E6%A8%B9/dp/4844336355)を読んだことで、CSSを設計という観点から見ることができるようになりました。
今後はただスタイルを適用するだけでなく、プロジェクトの設計に沿っているか、またより良い設計にできないかを考えながら実装したいと思います。

最後までお読みいただきありがとうございました！