and factoryのフロントエンド開発標準(CSS設計)について

## はじめに
この記事はand factory.inc Advent Calendar 2024 20日目の記事です。

https://qiita.com/ykm57/private/50694d5c64ac436c3341

社内でエンジニア勉強会に参加した際フロントエンジニアでのCSS設計について質問されたのでこちらにまとめようと思います。

## and factoryで扱うフロント開発標準(CSS設計)
- コンポーネントは**BEM設計**を採用している
    - [BEM公式ページ_日本語訳](https://qiita.com/yuta_web/items/6f2aa6b69e70b0b9f86c)
- ページレイアウトは**Tailwind CSS**を利用
    - レイアウト調整・間隔は**Tailwind CSS**を使用してカバーすることで命名コストが下がる
    -  [公式ドキュメント](https://v2.tailwindcss.com/)

### BEMとは何か
- Block(かたまり)、Element(要素)、Modifier(装飾)のそれぞれの頭文字で表しています
- 命名規則を定めることで、クラス名でチーム全体に共通認識を持たせることが出来る
- 可読性が高い(他の開発者が見た時に理解しやすい)

### BEMの設計思想
- Block、Element、Modifierを用いてクラス名を設定する
- 可読性を向上させることを目的として考案された設計思想である
- andfactoryでは冗長なclass名を避けるため基本的にはblockで完結されるようにclassの設定を行なっていく

### Block 
- 独立されており、ページのどこに配置しても機能する要素(再利用性)
- 見た目の状態ではなく、その領域が「何を示しているのか」が明確になるよう命名することが望ましい

<details><summary>例 一覧</summary>

| Name   | 読み方    |
| ----------- | --------- |
| attention   | アテンション    |
| body        | ボディ       |
| box         | ボックス      |
| button      | ボタン       |
| card        | カード       |
| chip        | チップ       |
| container   | コンテナー     |
| content     | コンテンツ     |
| description | ディスクリプション |
| detail      | ディティール    |
| favorite    | フェイバリッド   |
| footer      | フッター      |
| form        | フォーム      |
| header      | ヘッダー      |
| information | インフォメーション |
| list        | リスト       |
| navigation  | ナビゲーション   |
| ranking     | ランキング     |
| recommend   | レコメンド     |
| section     | セクション     |
| slider      | スライダー     |
| subTitle    | サブタイトル    |
| tab         | タブ        |
| table       | テーブル      |
| tabs        | タブズ       |
| tag         | タグ        |
| tags        | タグズ       |
| title       | タイトル      |
| video       | ビデオ       |
</details>

### Element
- 必ずブロックの中に存在する(これ単体で命名することはない)
- Element自体がBlockとして扱われることもある

<details><summary>例 一覧</summary>

| 共通 | Name  | 種別     |
| -- | -------- | -------- |
|    | address  | 住所       |
|    | body     | 中部       |
|    | category | カテゴリー    |
|    | date     | 日付       |
|    | feature  | 特徴       |
|    | head     | 上部       |
|    | icon     | アイコン     |
|    | image    | 画像       |
|    | inner    | 内側       |
|    | item     | 表やデータの項目 |
|    | lead     | リード文     |
|    | link     | リンク      |
|    | name     | 名前       |
|    | nav      | ナビゲーション  |
|    | photo    | 写真       |
|    | picture  | 画像       |
|    | price    | 値段       |
|    | tail     | 下部       |
|    | text     | 本文       |
|    | thumb    | サムネイル    |
|    | time     | 日時       |
|    | view     | 表示       |
---
| figure | Name    | 図形        |
| ------ | ------- | --------- |
|        | caption | 画像・図表の補足文 |
---
| form |  Name    | フォーム      |
| ---- | -------- | --------- |
|      | button   | ボタン       |
|      | checkbox | チェックボックス  |
|      | fieldset | 入力項目のグループ |
|      | input    | インプットテキスト |
|      | label    | ラベル       |
|      | radio    | ラジオボタン    |
|      | selector | セレクトボックス  |
|      | switch   | スイッチ      |
---
| table |  Name  | テーブル    |
| ----- | ------ | ------- |
|       | cell   | セル      |
|       | column | カラム (列) |
|       | row    | ロウ (行)  |

</details>

### Modifier
- Block、Elementの状態や装飾（レイアウト）のバリエーションを持たせるためのパターンを設定するための概念
- 条件で出し分ける際に使用したりする

<details><summary>例 一覧</summary>

| Name   | 種別  |
| -------- | ------- |
| active   | 動作している  |
| deactive | 動作していない |
| disabled | 無効      |
| enabled  | 有効      |
---
| Name     | 種別 |
| --------- | ---- |
| primary   | メインの |
| secondary | ２番目  |
| tertiary  | ３番目  |
---
| Name   | 種別     |
| ------- | ------- |
| error   | エラー     |
| success | 成功      |
| show    | 表示されている |
| hide    | 隠されている  |
| small   | 小さい     |
| big     | 大きい     |
| tiny    | 小さい     |
| large   | 大きい     |Hello, World'
</details>

### Tailwind CSSとは何か
- Webアプリケーションやウェブサイトのデザインとレイアウトを効率的に構築するためのUtility First(ユーティリティファースト)を掲げて設計されたCSSフレームワーク
- ユーティリティクラスを自由に組み合わせて活用し、よりオリジナリティの高いデザインのWebサイト及びWebアプリケーションを作成可能

### CSS設定する時の注意点
- **font-size指定について**
Tailwind CSSはpaddingなどの単位でremを使っているため`reset.css`や`Normalize.css`の設定で全体のfont-sizeを62.5%設定しないこと
- **tailwind.config.tsで設定した変数を利用する**
- **idにスタイルを定義しない。**
スタイルの優先度が高いので上書きするのが難しい
またコンポーネント内で使用するとユニークなid名でなくなってしまうため利用は好ましくない
- **!importantを乱用しない**
スタイルの優先度が最高になり上書きが難しくなるため
- **固定値は設定ファイルに記述し利用する**
頻繁に使われる画面サイズ・要素の幅と高さ・z-indexなど(とくにz-indexを直接で記載すると思わぬレイアウト崩れに繋がってしまうため必ず設定ファイルで管理すること)
- **CSSプロセッサはSCSSを推奨**
- **リセットCSSの導入**
メジャーなリセットCSSを導入し必要に応じて`reset.css`を作成する

### Class名記述方法
- 複雑なレイアウトであればBEMとTailwind CSSを合わせた記述をする

```html
<!-- BEM -->
<section class="content content--primary">
	<ul class="content__list">
		<li class="content__listItem">
		  ・リスト
		</li>
  		<li class="content__listItem">
		  ・リスト
		</li>
  		<li class="content__listItem">
    	  ・リスト
		</li>
	</ul>
<section>

<!-- ハイブリッド (BEM × Tailwind CSS) --> 
<section class="content px-2">
    <ul class="content__list pt-2">
        <li class="pb-2">
          ・リスト
        </li>
        <li class="pb-2">
          ・リスト
        </li>
        <li class="pb-2">
          ・リスト
        </li>
    </ul>
<section>
```

### 命名規則
- `block__element--modifier`の形で命名する(それぞれをアンダースコア２つとハイフン２つで区切る)
- 省略名称はできる限り使わないこと(省略内容に個人差があるため)
※プロジェクトやチームで元々省略名称が使われている場合は合わせた名称をつける

```md
// OK
.button, .massage, .error .banner

// NG
.btn, .msg, .err、 .bnr
```
- クラス名はそのエレメントが何を指しているのかわかりやすい名称にする
※デザインを名称に当てるのは避けること(デザイン変更された場合に見た目とクラス名に反りが出てしまうため)

```md
// GOOD
.submitButton, .cancelButton
.entryForm__textarea, header__logo .list__item

// NG
.greenButton, .darkButton　
.box--borderBold
```

- ネストが深くなるような記述をしないこと
※BEMの場合BEまではネストさせない

```scss
// GOOD
.block {
  &--modifier {
  }
}
.block__element {}
.block__element {
  &--modifier {
  }
}

// NG 
.block {
  &__element {
    &--modifier {
      ::after {
      // ネストが深い
	} 
  }
}
  &__elementContent {
    &View {
    // .block__elementContentViewとになるが可読性が悪い
	}
  } 
}
```
- 数字から始まる、または数字のみセレクタは機能しないので利用しない
- 詳細度が高すぎるセレクタの指定をしない
```scss
div a {...} // すべてのdivのなかaに影響がでるので　NG
.block__element {
  a {} // block__element以降のaが全て影響されてしまう NG
  > a {} // 本来classをつけた方が好ましいが小さい要素であれば OK
}
```
- javascriptで利用されている予約語や定数を名称で利用をしない
- ハイフンやアンダースコアで始まる名称は使わない
    - BEM設計のルールと混ざると可読性が下がるため
- classやidの名称に一文字だけを指定しない(セマンティックな名称になってない)
    - 名称からなにを指し示しているかわかる名称を心がける
- 全角スペースや半角スペースを名称で利用しない、また機種依存文字を利用しない(エラーの原因になるため)

## まとめ
and factoryでの開発標準について今回はCSSをピックアップして記事にしました！

フロントエンジニアのメンバーも増えてきているため開発標準が整っていることで環境設定周りや、ディレクトリ構成などを迷うことなくプロジェクトを立てることができます。
他にもコンポーネントの設計やlintの設定などさまざまなことに関してまとめています。
先輩エンジニアを中心にフロントメンバーで話合いながら今後の指標を決めていって初期開発でスムーズに環境設定を行っていきたいと思います！
記事を書くのに慣れておらず読みにくい部分もあったかもしれませんが最後まで読んでいただきありがとうございます！