フロントエンドの命名や設計の基本と自分の現在の設計

## はじめに

フロントエンドのコーディング時の命名や設計についてまとめました。
命名や設計についてあらかじめ知っておくと気をつける点や全体を意識してコーディングをおこなえるかと思います。
現在の自分自身の設計の仕方を参考に掲載しますので、一例として読んでいただければと思います。

※ フロントエンドの技術・知識が業務レベルの方には物足りない内容です。


## 命名規則の種類

各要素一つずつに対して命名していきますが、複数の単語で命名することが多いです。
これは他の要素と被らないようにするためです。もし一つの単語にした場合、最初は一つだけだったのに後から同じようなものがでてきてかぶってしまう、なんていうことは想定に難しくありません。（場合によって回避策はあります。）

また、ほとんどの場合が英数字＋いくつかの記号で命名することが多いですが、無秩序に命名してしまうと後で見返す時に探し出すのが辛くなってきます。

そこで、命名規則をサイト単位もしくはプロジェクト単位で決めます。

一般的な命名規則は以下です。

| 名称 | 表記例 | 説明 | 用途 |
| --- | --- | --- | --- |
| キャメルケース | camelCase | 最初の単語以外の文字の先頭を大文字。<br>ローワーキャメルケースとも言う。 | 変数、関数。 |
| パスカルケース | PascalCase | 文字の先頭を常に大文字。<br>アッパーキャメルケースとも言う。 | クラス（プログラミングの抽象データ型の方）。 |
| コンスタントケース | GLOBAL_OBJECT | すべて大文字、単語をつなげる場合はアンダースコア。 | 定数、グローバル変数、その他強い意味を持たせたい時。 |
| スネークケース | snake_case | 文字の単語間にアンダーバー。 | apiで返却されるjson objectのkey |
| ケバブケース |  チェインケース | kebab-case | 文字の単語間にハイフン。 | htmlタグの属性。<br>htmlタグのclass指定。 |
| - | _privateVar | 変数の最初にアンダースコア。 | プライベート変数。 |

上記の他に以下のような規則も必要に応じて設けると良いでしょう。

* 接頭辞（プレフィックス）を必要に応じて付ける（例：is-xxxx）
* 単語は略語を使用しない（NG例：cnt, hdg, tbl）

### 参考

[変数名の命名規則/＊＊ケースの使い分け](https://qiita.com/am_nimitz3/items/7b01af53751dba5d8fb1)

## 命名方法

命名規則が決まればそれに則って命名すれば良いのですが、どういう単語を使えば良いのか指標がほしいところです。
英単語がすぐ出てこないような時は[ネーミング辞書 Codic](https://codic.jp/)を使ってみると良いです。命名の参考としては良いツールだと思います。

目的や内容によっては汎用的に使える英単語も存在します。例えば、レイアウト用の要素としてcontainer, row, col。ジャンル・業界別の要素としてabout, results,productsなど。

レイアウト用のclass名や汎用class名に関してはいろんなCSSフレームワークのコードを見て研究することで学ぶことができます。いろんなコードを見ていく中で「これは直感的で使いやすい」「あっちは長めの単語だったがこっちの方が短くて好き」などいろんなことを感じて落とし込んでいくと自分の中で徐々に指標ができてくると思います。

あとは競合他社の命名を数社見るのも良いと思います。同じようなものが数社で同じ命名であれば、業界として一般的な単語なのかもしれない、という推測ができます。

上記のように手がかりはWeb上で探せます。時間に余裕があれば、いろんなWebサイトのコードを見て参考にすると良いと思います。

※経験の少ない方のコードも多々あるのですべて鵜呑みにするのは避けましょう。ちなみに大手サイトでも参考にならないコードが割と多いです。

### 小話

命名は「英単語が一般的でローマ字はダサい」という声をたまに聞いたりしますが、意図的に使うケースも存在するようです。
例えば、会計や司法などといった専門用語を使うような場合、英単語にすると余計わかりづらくなったり、そもそもぴったり合う英単語がなかったりするそうです。そういった専門用語をわかりやすくする目的でアッパーケースのローマ字で使ったり、日本語に対応している言語もあるので日本語を使うといったところもあるようです。

## CSS設計の有名な設計思想

命名規則・命名方法と合わせて重要なのがCSS設計の設計思想です。
命名規則に沿ってCSSフレームワークや他のサイトを参考に命名していっても、サイト全体でどう設計するかを考慮しないと破綻しやすいです。
CSS設計のポイントとして以下のことを強く意識しておこなうことが大切だと言われています。  

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

これらを満たすためにいろんな設計思想が生まれていますが、以下が有名設計思想です。

* OOCSS
* BEM
* SMACSS
* FLOCSS


### OOCSS

OOCSS（Object Oriented CSS）は、オブジェクト指向にもとづいて考案された設計思想です。
Bootstrapがこの思想のもとに設計されています。

#### 特徴

* Container（入れ物）とContents（中身）を分けて考える
  * .container > .contentsのように依存関係にせず、.containerと.contentsを独立させる（再利用性が向上）
* Structure（基本構造）とSkin（見た目）を分けて考える
  * .btnで基本構造を定義し、.btn-primaryで見た目を変更する

```html:HTML
<!-- oocss.html -->
<h1>OOCSS(Object Oriented CSS)</h1>
<ul class="menu">
  <li class="item item-large">link</li>
  <li class="item item-active">active</li>
</ul>
```
```css:CSS
/*oocss.css */
.menu {
  list-style-type: none;
}
.item {
  width: 80px;
  margin-bottom: 5px;
  color: #4486F7;
  border: 1px solid #4486F7;
  text-align: center;
}
.item-large {
  width: 100px;
}
.item-active {
  color: #fff;
  background-color: #4486F7;
}
```

#### ポイント

レゴのようにパーツごとにclassを用意し、HTMLタグに必要なclassを必要な数だけ付けて目的を実現します。HTMLタグにclassをつけるだけなので運用時にはHTMLを触るだけでCSSを触る必要がなくラクそう♪ ・・・と思いきや、用意されたclassだけでは賄えない場合はCSSを追加する必要があるしHTMLを触る時にどういったclassが用意されているのかを把握していないと適切に使用できない（場合によっては同じものを違うclass名で作ってしまう）ので、OOCSSだけで設計するのであればその辺りをカバーできるものを用意したほうが良いでしょう。
用途としては、CSSを頻繁に触るのが難しいような案件でCMSやシステムで構築されたサイトなどが挙げられます。
特徴にも書きましたが、OOCSSの目的を分ける発想はとても素晴らしいので、命名する時の基本として捉えてしまって良いと思います。

### BEM

BEM（Block Element Modifier）は、独特な命名規則（MindBEMding）で有名な設計思想です。

#### 特徴

* Block
  * もととなる要素
* Element
  * Block内にある要素
* Modifier
  * 変化した状態を表す要素

3つの要素を`Block__Element--Modifier`のように結合してclass名を決めます。公式では、Elementはアンダースコア2つ（`__`）で結合、Modifierはハイフン2つ（`--`）で結合する規則になっています。  

```html:HTML
<!-- bem.html -->
<h1>BEM(Block__Element--Modifier)</h1>
<ul class="menu">
  <li class="menu__item--large">link</li>
  <li class="menu__item--active">active</li>
</ul>
```

```scss:SCSS
/* bem.scss */
.menu {
  list-style-type: none;
}
.menu__item {
  width: 80px;
  margin-bottom: 5px;
  color: #4486F7;
  border: 1px solid #4486F7;
  text-align: center;
}
.menu__item--large {
  @extend .menu__item;
  width: 100px;
}
.menu__item--active {
  @extend .menu__item;
  color: #fff;
  background-color: #4486F7;
}


/* bem.scss */
.menu {
  list-style-type: none;

  &__item {
    $element: #{&};
    width: 80px;
    margin-bottom: 5px;
    color: #4486F7;
    border: 1px solid #4486F7;
    text-align: center;
    &--large {
      @extend #{$element};
      width: 100px;
    }
    &--active {
      @extend #{$element};
      color: #fff;
      background-color: #4486F7;
    }
  }
}
```

#### ポイント

BEMが優れている点は、他の要素との依存が減り影響範囲を気にする負荷が減ることです。なので多少雑に書いても大丈夫です。というのも短い時間の中で影響範囲を気にしながらではスピードが出ない場合もあり、影響範囲をある程度気にしなくても良い点はセールスポイントだと思います。（それでもclass名がかぶってしまう場合があるので完全ではないです。）

デメリットとしては、class名がどうしても長くなりがちで同じようなclass名が並ぶので特定のものを見つける時に紛らわしくて作業者の精神的負荷がかかります。あとCSSプリプロセッサを併用しないととても辛いです。

BEMで汎用的に活かせる点は、ある要素（Block）を起点にその子孫要素（Element）やパターン違い（Modifier）を考える視点を持つことです。OOCSSにも被る部分もありますが、モジュール単位ではBEMの発想で組み立てやすいと思います。

### SMACSS

役割ごとに分離した設計思想です。

#### 特徴

* Base
  * サイト全体のデフォルトスタイルを定義する
  * reset.cssやnormalize.css
* Layout
  * Moduleの配置を決める
  * プレフィックスに「l-」をつける（例: .l-main、.l-sub）
* Module
  * 再利用可能なパーツ
* State
  * LayoutやModuleの変化した状態
  * プレフィックスに「is-」をつける（例: .is-active、.is-error）
* Theme
  * LayoutやModuleのTheme
  * プレフィックスに「theme-」をつける（例: .theme-color）

```html:HTML
<!-- smacss.html -->
<h1>SMACSS(Scalable and Modular Architecture for CSS)</h1>
<div class="l-container">
  <ul class="menu">
    <li class="menu-item is-large">link</li>
    <li class="menu-item is-active">active</li>
  </ul>
</div>
```

```scss:SCSS
/* smacss.scss */
.l-container { /***/ }
.menu {
  list-style-type: none;
}
.menu-item {
  width: 80px;
  margin-bottom: 5px;
  color: #4486F7;
  border: 1px solid #4486F7;
  text-align: center;
  &.is-large {
    width: 100px;
  }
  &.is-active {
    color: #fff;
    background-color: #4486F7;
  }
}
```

#### ポイント

役割ごとにディレクトリを分ける指標として参考になります。また、マルチクラスとして状態を別classとしてつける手法は個人的に好みです。
小さいサイトだとこれぐらいの分け方で割といけます。大きくスケールしそうであれば後述するFLOCSSの方が良いかもしれません。
SMACSSは、小規模サイト向けのディレクトリ構成として参考になります。

### FLOCSS

FLOCSS（Foundation Layout Object CSS）は、OOCSSやBEM、SMACSSのいいとこ取りをした設計思想です。

#### 特徴

* Foundation
  * サイト全体のデフォルトスタイルを定義する
  * reset.cssやnormalize.css
* Layout
  * Objectの配置を決める
* Object
  * Component
      * 再利用可能なパーツ
      * プレフィックスに「c-」をつける（例: .c-btn、.c-btn_primary）
  * Project
      * Componentにするほどでもないパーツ
      * プレフィックスに「p-」をつける（例: .p-article、p.article__title）
  * Utility
      * 汎用クラスで単一のスタイルを持つ
      * プレフィックスに「u-」をつける（例: .u-clearfix、.u-block）

```
├ foundation
│ ├ _base.scss
│ └ _reset.scss
├ layout
│ ├ _main.scss
│ └ _sidebar.scss
└ object
   ├ component
   │ ├ _button.scss
   │ └ _grid.scss
   ├ project
   │ ├ _articles.scss
   │ └ _profile.scss
   └ utility
      ├ _clearfix.scss
      ├ _margin.scss
      └ _text.scss
```

```html:HTML
<!-- flocss.html -->
<body class="flocss">
  <h1>FLOCSS</h1>
  <div class="container">
    <ul class="o-menu">
      <li class="c-item c-item--large">link</li>
      <li class="c-item c-item--active">active</li>
    </ul>
  </div>
  ...
</body>
```

```scss:SCSS
/* flocss.scss */
.flocss {
  .container { /***/ }
  .o-menu {
    list-style-type: none;
  }
  .c-item {
    width: 80px;
    margin-bottom: 5px;
    color: #4486F7;
    border: 1px solid #4486F7;
    text-align: center;
  }
  .c-item--large {
    width: 100px;
  }
  .c-item--active {
    color: #fff;
    background-color: #4486F7;
  }
}
```

#### ポイント

FLOCSSは大規模サイトもしくはがっつりCSSを管理していきたい/いける場合に活用すると良いかと思います。逆に小規模だと再利用可能なパーツがそもそも出なかったり汎用classも特に必要なかったりします。しかし大規模サイトにスケールしても良いようにFLOCSSで設計しておくのはアリだと思います。

万能なように見えるFLOCSSですが、「Utilityはレスポンシブだとボックスレイアウト関連やフォントサイズとかで弊害が起きる可能性がありそう」「プレフィックスを各所につけるのはやりすぎではないか？運用面で活用できる反面制作スピード落ちないか？」とかいろいろ検討部分はあります。ベストプラクティスを盛り込んでいるもののサイト・プロジェクトに応じてどこまで採用するかはしっかり検討したほうが良いです。

#### 参考

[OOCSS、BEM、SMACSS、FLOCSS、RSCSSを比較して自分にあった設計思想をみつける](https://kuroeveryday.blogspot.com/2017/03/css-structure-and-rules.html)

## CSS設計をおこなう

有名な設計思想をいくつか挙げました。いずれも一長一短あります。結局は有名な設計思想を参考にサイト・プロジェクトごとに独自のCSS設計をおこなうことになります。

以下は、個人的な観点でどのようにCSS設計をおこなっているか参考にまとめました。

### 有名な設計思想からの採用

| 設計思想 | 採用部分 | 具体的な使用場所 |
| --- | --- | --- |
| OOCSS | 目的に応じてclassを分ける = マルチクラス前提 | classをつける要素すべて<br>1要素に対して無理にシングルクラス（1classのみ）にしない | すべて<br>（class設定のベースの考え方として採用する） |
| BEM | ある要素（Block）・その子孫要素（Element）・パターン違い（Modifier）を考える視点を持つ<br>※区切り文字は別途ルールを設ける | モジュール単位<br>（SMACSSでいうModule、FLOCSSでいうComponent） |
| SMACSS | 役割ごとにディレクトリ・ファイルを分割<br>状態classにプレフィックス「is-」をつける | ディレクトリ・ファイル構成<br>状態に応じてスタイルを設定する箇所 |
| FLOCSS | 大規模へのスケールを想定した設計手法のミックス | ディレクトリ・ファイル構成 |

### 命名規則の新設

| class | 接頭辞 | Block | Element | 例 |
| --- | --- | --- | --- | --- |
| 汎用class | ○ | ○ | × | .ttl-b（タイトルBパターン）<br>.list-num（番号付きリスト） |
| 固有class | × | ○ | ○ | .headerNavList（ヘッダーナビ一覧）<br>.headerNavList_1st（ヘッダーナビ一覧の第1階層） |
| 状態class | ○ | × | ○ | .is-active |

* 接頭辞は状態classまたは汎用classの場合に使用し、区切り文字はハイフンを使用する
* 接頭辞は一般的で伝わる単語は略語を使用する
  * 例）txt, img, bg, ttl
* Block・Element間の区切り文字はアンダースコアを使用する
* Block・Element内はキャメルケースを採用する
* Modifierは状態classとしてBlock・Elementと切り離しマルチクラスとして併用する

### ディレクトリ・ファイル構成の設計

SMACSS・FLOCSSを参考にプロジェクトに応じた構成にします。

```
├ settings
│ ├ _mixin.scss
│ ├ _variable.scss
│ └ _media.scss
├ vendor
│ ├ _normalize.scss
│ └ ├ ...
├ base
│ ├ _base.scss
│ ├ _typography.scss
│ ├ _embeded.scss 
│ ├ _list.scss
│ ├ _table.scss
│ └ _form.scss
├ _layout.scss
├ components
│  ├ ...
├ page
└  ├ ...
```

最近は大体このような形に設計することが多いですが、Vue.jsやNuxt.jsを使うようになってからコンポーネント単位で上書きしないように閉じ込められるようになり、CSS設計の再構築を検討したほうが良さそうな印象を受けます。特に複数のコンポーネントにスタイルを当てたい場合、assetsディレクトリに入れるのか、それともcomponentsディレクトリのルートに入れるのかは悩ましいところです。

## さいごに

命名や設計はある程度ベストプラクティスな考え方や手法があるものの、新たなものが生まれてくるものでもあります。また、コーディングするプロジェクトの要件やステークホルダーによっても変えたほうが良い部分が出てきます。

設計はどこまで考えられているかで寿命が変わってきます。5年間ぐらい破綻しない設計だと良いと思います。（更新や改修の頻度によりますが、一般的に5年ぐらいの周期でリニューアルをかけるプロジェクトが多い印象です。）

命名や設計に悩んだら参考にしていただければと思います。