ホームページを眺めながらCSS設計の初歩を学ぼう【BEM Mix体験編】

## はじめに
この記事は[『CSS設計完全ガイド』](https://www.amazon.co.jp/CSS%E8%A8%AD%E8%A8%88%E5%AE%8C%E5%85%A8%E3%82%AC%E3%82%A4%E3%83%89-%E8%A9%B3%E7%B4%B0%E8%A7%A3%E8%AA%AC-%E5%AE%9F%E8%B7%B5%E7%9A%84%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E9%9B%86-%E5%8D%8A%E7%94%B0-%E6%83%87%E5%BF%97/dp/429711173X)という書籍の内容を元に、実際のホームページを見ながらCSS設計にふれてみよう！という内容になっております。

前回はCSS設計の第一歩として、**「抽象化」**・**「分ける」** という２つの視点からホームページを眺めてみて、その中で共通するメディアやボタンといったコンポーネントについてお話ししました。

今回はそこからもう少し視野を広げて、複数のコンポーネントが集まったセクションがあり、そのコンポーネント同士の隙間(margin)をどのように設定するか、というテーマで考えていきたいと思います。

## 前回の振り返り
:::note info
前回の記事はこちら↓
:::
https://qiita.com/shimamoooon/items/314f8484de4b9f1a1abd

<br>
最初に軽く前回のおさらいをしておきます。

ボタンとメディアという２つのコンポーネントの関係について説明しました。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333738333232322f30336635343564352d343662632d306230342d623464332d6539303038336632616333632e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/f7d1cf6a-c81d-7919-dff6-83624ebfc6e8.png)
  
  
このメディアにはボタンが内包されており、ボタンのクラス名を`.media-btn`とするのか、`.btn`とするのかという問題でしたね。

そして、この場合は`.btn`として、メディアとボタンそれぞれが独立している方がCSS設計としては正しい、というお話でした。
```html
<div class="media">
  <img src="../images/sample.jpeg" alt="sample" class="media-img" />
  <div class="media-body">
    <h3 class="media-title">タイトルタイトルタイトル</h3>
    <p class="media-text">
      テキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
    </p>
    <a href="#" class="btn">詳細はこちら</a>
  </div>
</div>
```

## 今回のテーマ
では今回はCSSに焦点を当てて、メディアが複数集まったケースを考えてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/a5c659b5-e3b0-dcde-20b1-ad760cd67526.png)

ホームページでよく見る形ですね。

HTMLとしては、前回登場した`<div class="media">`が３つ並んでおり、それを囲むdiv要素があるといった形です。

さて、今回のテーマは **`<div class="media">`の隙間（margin)をどのようにCSSで書くか**なのですが...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/fe694f4a-4018-2f72-fb53-710a0c52d351.png)


## スタイルの上書きの発生

まず真っ先に思い浮かぶのは`<div class="media">`にmargin-bottomを指定することだと思います。

（最後の要素はmargin-bottomが不要のため、:last-childで０としています。）

```css
.media {
    margin-bottom: 30px;
}
.media:last-child {
    margin-bottom: 0;
}
```

:::note info
余談ですが、こうした複数のアイテムが並ぶレイアウトで最後の要素のみスタイルを付けたくない場合、`:not()`を使うことでコードがスッキリします！
非常に便利ですので覚えておくと◎
```css
/* これで上と同じ意味のコードになります */
.media:not(:last-child) {
    margin-bottom: 30px;
}
```
:::

これで特段問題なさそうですし、事実このようにスタイルを当てているホームページも多いのですが...

懸念点を挙げるとすれば、このメディアをserviceだけではなくcompanyという別のセクションでも使うことになったとき、この`margin-bottom: 30px`を上書きしなければならない可能性があるのです。

<br>
たとえば、companyセクションではメディア同士の隙間が30pxではなく60pxだったとします。

メディアには既に`margin-bottom: 30px`を付与しているため、**companyセクションの.mediaについてのみスタイルを上書き**してやる必要がありますね。
```css
/* 既存のコード */
.media {
    margin-bottom: 30px;
}
.media:last-child {
    margin-bottom: 0;
}

/* .mediaのスタイルを上書き */
.company .media {
    margin-bottom: 60px;
}
```

<br>
実際どのようにスタイルが上書きされているかというと、Google Chromeの開発者ツールで見るとわかりやすいです。

![スクリーンショット 2024-06-15 21.31.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/dcc78203-ace3-6f99-e556-40b116222e3f.png)

このように既存の`.media`の`margin-bottom: 30px`が打ち消されているのがわかりますね。

正直この程度であればこのままでも問題ないのですが、大規模なウェブサイトでこうしたスタイルの上書きをどんどん繰り返していると、いずれ修正が非常に困難なCSSになってしまいます😭

この問題を解決すべく、CSS設計における１つの対処方法をご紹介します！


## マルチクラスを採用する
CSS設計では、そもそもこのような不要なスタイルの上書きを起こさないように、**コンポーネントはレイアウトに関わるスタイルを持たない**という考え方を取っています。

ではどうするかというと、marginなどのレイアウトに関わるスタイルは`<div class="media">`にもう1つ別のクラスを付与してそのクラスが担当すればOK、という方法です。

まずはコードを見てみましょう。

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/6aaed713-1b7b-42b6-7f78-0761f2a473cd.png)

このように`<div class="media">`に`.service-media`という別のクラスを与えて、そのクラスがmargin-bottomを担当すれば`.media`がmarginを持つ必要もなく、スタイルの上書きも不要になります。

![b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783222/d1c979ab-16c7-9dc4-ec57-b2deeedd3abf.png)

<br>
cssはこのように変わります。

```css
/* メディアコンポーネント */
.media {
    /* margin-bottomは指定しなくてよい */   
}

/* serviceセクションのメディア */
.service-media {
    margin-bottom: 30px;
}

/* companyセクションのメディア */
.company-media {
    margin-bottom: 60px;
}

```

このようにマルチクラスにすることで、メディアがmarginを持つことなく、スタイルの上書き問題も解消されました！

## 今回のタネあかし
実はここまでお話ししてきた内容は、CSS設計の手法の１つである「BEM」の「Mix」というテクニックを使っていました。

[Mixes](https://en.bem.info/methodology/css/#mixes)

おそらくCSSを勉強し始めると、早い段階で「BEM」を目にすると思います。
 
BEMについて解説されている記事はたくさんありますが、今回は難しい用語や説明は抜きにして、**もっとCSS設計の根本的な考え方に触れてもらいたかった**ので、BEMの説明はあえて省かせていただきました:pray:

ちゃんとしたBEMやMixの書き方が気になる方は、上記のリンクを見てみてください。

今回の記事は
- 思いつくままにCSSを書いていると、スタイルの上書きが頻発してあとで苦しくなる
- そうなる前に、ちゃんと考えてmarginとか付けようね

ということが伝わっていたら嬉しいです！

## おわりに
今回はCSS設計の１つ、BEMのMixについて具体的にホームページの一部を見ながら説明してみました。

実はこのマルチクラスの設計によって、もう１つ「詳細度が一定に保たれる」というメリットも生まれるのですが、そちらについては次の記事でご紹介したいと思います！


## 参考
- [CSS設計完全ガイド](https://www.amazon.co.jp/CSS%E8%A8%AD%E8%A8%88%E5%AE%8C%E5%85%A8%E3%82%AC%E3%82%A4%E3%83%89-%E8%A9%B3%E7%B4%B0%E8%A7%A3%E8%AA%AC-%E5%AE%9F%E8%B7%B5%E7%9A%84%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E9%9B%86-%E5%8D%8A%E7%94%B0-%E6%83%87%E5%BF%97/dp/429711173X)
- [BEM](https://en.bem.info/methodology/)