今時のフロントエンドエンジニアに見て欲しい保守性の高いHTML/CSSの書き方

これは[POLプロダクト部 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/pol) 2日目の記事です。

昨日の[@mizno](https://qiita.com/mizno)さんからバトンを頂きました。柳沢です。
POLではフリーランスとして主にフロントエンドの領域を担当しております。

最近のフロントエンドのやること多いですよね。
TypeScriptで型定義して、React書いてーredux書いたと思ったら、非同期の部分でthunk使わなあかんくてそれも書いて
API通信してーとか、
BFFとかやり出したら、ほんまにやることが多いです。

なのでどうしてもHTML/CSSの比重って下がりがちになってきます。
それにReactなどでコンポーンネント分割してたりすると、以前ほどCSSを設計する必要もなくなってきてます。

だからと言って、あまりに考え無しに書いてると、メンテナンスの段階において結構面倒くさい事になることが多いです。

なので最低限これぐらいは気をつけてもらえると、メンテナンスコストも下がるぜ！ってのを書いていこうと思います。


## Figmaからの丸コピ

最近のデザインツールとしてFigaを使う機会が多くなってきました。
FigmaはCSSのプロパティをコピー出来てすごい便利なんですが、それが弊害になってるなと最近感じます。

``` CSS
.hoge {
  font-style: normal;
  font-stretch: normal;
  color: rgb(58, 62, 73);
  width: auto;
  height: 7px;
  font-size: 16px;
  font-weight: bold;
  line-height: 1.49;
  letter-spacing: 0.4px;
  margin-bottom: 10px;
}
```

こんな感じの最近よく見かけるなと思ってる方も多数おられると思います。
典型的なfigmaからのCSS丸コピですね
font-style、font-stretch、widthがデフォ値やし
colorもHEX値ではないし、heightも指定されているし、letter-spacingやline-heightの値も微妙

確かに状況によっては上記プロパティ設定することもありますが、さすがにここまで揃えばそんな感じでもないですよね。
で、デベロッパーツールで試しに外してみると、やはり何も変わらず。

「別に変わらんならええやんけ！」って思われる方もおられると思いますが、いくら不要やと思ってもそれにわずかでも使う時間ってもったいないしし、修正には気を遣いますし、ノイズが多いと視認性も悪くなります。

**なので、本当に必要なプロパティだけ持ってくるようにしてください。**

参考に今回ならここまで減らせてだいぶスッキリしました。

``` CSS
.hoge {
  color: rgb(58, 62, 73);
  font-size: 16px;
  font-weight: bold;
  line-height: 1.4;
  margin-bottom: 10px;
}
```

## divdivしないで

``` html
div >
  div >
    div > 
      div タイトル
    div > 
      div 本文
    div > img

```

ちょっとこれは極端ですが、大半のHTML要素がdivで構成されてしまっているものもよく見かけます。
さらに **styled component** を使ってたらPRなんかではなかなか気づくのも難しいです。

これって間違いではないんですが、
**やはりHTML構造的にはおかしいです。**

さらにデバッグしようとデベロッパーツールで見てみるとこんな感じになってしまい、対象の要素が見つけにくくなってしまいます。

![スクリーンショット 2020-12-01 21.57.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43289/e960e0c8-e514-8266-4895-1536b8f4473b.png)

例としてですが、以下のような感じだと、HTML構造的にも意味が出てくるし、デベロッパーツールで見たときも見分けが付きやすくなるかと思います。

``` html
section >
  div >
    header > 
      h1 タイトル
    div > 
      p 本文
    figure > img

```

## 余白の定義

### marginとpaddingの違い
marginとpaddingの違いってなんでしょうか。
HTMLの入門書等には
> paddingは余白を要素の中に作る
marginha余白を要素の外に作る

とありますがいまいちピンと来ないです。なので

**marginは兄弟要素間の余白、paddingは親子要素間の余白**

と考えればわかりやすいかと思います。
![アセット 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43289/e73f69a1-005e-4448-a36c-66385b1c87bc.png)

このmarginとpaddingがごっちゃになってると以下の画像のような感じに、要素間の余白がmarginとpaddingで二重で定義され、
さらにmarginの総裁が起こって、何がなんやらよくわからない状態になり、余白の調整をするのが困難になります。

![アセット 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43289/b9e97e45-019b-d518-88c2-94ec0d262005.png)

特に回収をよく行っていると、marginとpaddingがあらゆるところに設定されこれがさらに複雑になったりします。


### margin設定の規則
marginとpaddingの違いもそうなんですが、marginはtopかbottomどちらで設定するか、leftとrightどちらで設定するかもプロジェクトで決めておいた方が良いです。
余白の規則を決めておかないと、各人がなんとなくで余白を設定しmarginの相殺が起こり、それを上書きする必要が出たりしCSSが複雑になります。


## heightは指定しない
最初にfigmaのところでも少し書いたんですが、figmaのプロパティーをそのまま持ってくるとheightが指定されていることがよくあります。
figmaからコピーした当初は特に問題はない感じですが、font-sizeがheightを超えた場合おかしなことが起こります

![スクリーンショット 2020-12-02 1.31.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43289/0378fe54-4a26-9639-c56c-9b8254ca568e.png)

``` css
.title  {
  height:5px;
  font-size:20px;
  margin-bottom:10px
}
```

画像見てもらえばわかりますが、heightに5pxが設定されているんですが、font-sizeが20pxになっているので
要素としては5pxより大きくなっています。
しかしmarginは本来のheight:5pxのところからの設定になるので以下のようにmarginを設定しているにも関わらず、想定しているものとは異なる結果になってしまいます。

![スクリーンショット 2020-12-02 1.39.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43289/bfb70c38-56bf-4ca8-7105-c1af37e6064b.png)


本来heightって指定する場面は少ないように感じます。
高さが欲しい場合は **padding** を設定してそれで高さを作るのが良いかと思います。

## inline-blockは使わない
要素を横並びする時に以前はinline-blockを使うことが多かったですが、知ってる方も多いかと思いますが、inline-bockでの要素間で改行があると、そこに隙間ができてしまいます

#### inline-blockの場合
![スクリーンショット 2020-12-02 2.10.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43289/16e8d0f6-eb73-6be5-6d47-2d566cdf25fc.png)

#### flex-boxの場合
![スクリーンショット 2020-12-02 2.10.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43289/3b56630e-f315-8067-53e3-4bdf542d5405.png)


実はこの隙間結構厄介で、ただ隙間があるだけならいいんですが、これのおかげで段落ちしたり、横のラインがガタガタになったりします。
なのでここは大人しくflex-boxでやっていくのが、吉です。


## htmlの入れ子ルール
htm5から **コンテンツモデル** が導入されhtmlタグの入れ子ルールが制定されました。
これは明確に正解不正解があり、例えば[W3Cバリデータ](https://validator.w3.org/)などでエラーになるので比較的わかりやすいものではあります。

例えば極端な例ですが

```
ul > p
```

これはW3Cバリデータでは以下のようにエラーとなります。
![スクリーンショット 2020-12-02 2.33.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43289/80ac116a-e426-b397-80b5-bc6b9da1a011.png)

少し間違えやすいのだと

```
p > h1
```

こういうのもエラーとなります。

またmaterial-uiとか使ってると、意図しないところで入れ子が起こりエラーとなることが多いので
https://yoshikawaweb.com/element/
こういったサイトで確認するのが良いかと思います。

このエラーは環境によってはデベロッパーツールでエラー表示されることがあり、デバッグするのが困難になります。

## まとめ
HTML/CSSって多少粗めに書いても、それなりに表示されますし、figmaなどのデザインツールでのCSSプロパティーをコピーすれば
比較的綺麗に表示されます。
ただやはり、最低限気をつけているといないのとでは、その後の保守運用の工数に結構な差が出ることがありますし、あまりメンテナンスできていないCSSを修正するのは正直すごいストレスにもなるので、ここで記載した最低限のところを押させて作成し皆が良いフロントエンド制作ライフを送っていければと切に願っております。