[CSS設計] 私のためのFLOCSSまとめ

# FLOCSSとは
「Foundation Layout Object CSS」
OOCSSやBEM、SMACSSのいいとこ取りをしたCSS設計思想。

# 構造
dartsassに移行しましたので構造を修正しました。

https://yumegori.com/dart-sass-method
```
scss/
├─ foundation/
│　├─ _base.scss
│　├─ ...
│　├─ index.scss
├─ global/
│　├─ mixin/
│　│　├─ _hover.scss
│　│　├─ ...
│　│　├─ index.scss
│　├─ variable/
│　│　├─ _color.scss
│　│　├─ ...
│　│　├─ index.scss
│　├─ index.scss
├─ layout/
│　├─ _header.scss
│　├─ ...
│　├─ index.scss
├─ object/
│　├─ component/
│　│　├─ _button.scss
│　│　├─ ...
│　│　├─ index.scss
│　├─ project/
│　│　├─ _header.scss
│　│　├─ ...
│　│　├─ index.scss
│　├─ utility/
│　│　├─ _color.scss
│　│　├─ ...
│　│　├─ index.scss
└─ common.scss
```

## ディレクトリごとに読み込む

`@import` が非推奨になりdartsassに移行したことで、読み込みには`@use`を使用します。
後で説明する変数、mixinの `global`ディレクトリの読み込みには`@forward`を使用します。



各ディレクトリに設置した`index.scss`にディレクトリ内のSCSSファイルを読み込ませます。

そしてその `index.scss` を`common.scss` に読み込ませます。

読み込みをディレクトリごとにすることで、ファイル追加時に同じディレクトリの`index.scss` に記載すればいいだけなのでファイルが膨大になっても、追記しやすく時短になります。

```scss
// common.scss
@use "foundation";
@use "layout";
@use "object/component";
@use "object/project";
@use "object/utility";
```

```scss
// object/project/index.scss
// このファイルに追記するだけ
@use "header";
@use "drawer";
@use "nav";
...
```

## :open_file_folder: Global

dartsassに移行したことで、**変数、mixinは使用するファイル内に読み込ませる必要があります。**

1行で読み込ませるために`global`ディレクトリを追加しました。
dartSassについてはこちらの記事を参考にしてください

https://qiita.com/super-mana-chan/items/fbfa5447ae893bed3b4c

# :open_file_folder: Foundation
サイト全体のデフォルトスタイルを管理するディレクトリ。

## :page_facing_up: reset.scss
ブラウザのデフォルトのスタイルをリセットするcssを定義。
destyle.cssをCDNで読み込んで使用しています。（アプデにすぐ対応できるから）

>destyle.cssとは...
> デフォルトのスタイリングをほぼ無くすことができるリセットCSS
> * box-sizing: border-box;が含まれている
> * iOSでタップした時のグレー表示も消してくれる
> * marginは基本的に0
> 
> 抜粋：[2020年版！おすすめのリセットCSSまとめ#destylecss \| Web Design Trends](https://webdesign-trends.net/entry/8137#destylecss)


## :page_facing_up: base.scss
サイトを構成する上で、デザインの基本の下地、土台となるスタイルを定義
* **タグ自体にスタイルを定義**
* :page_facing_up: reset.cssで足りなかったリセットを追加
* 基本の文字サイズやフォントファミリーなどの追加

# :open_file_folder:  Layout
各ページを構成する、**ヘッダー、メインコンテンツエリア、コンテナ、フッターなどのレイアウトに関するスタイルをエリアごと**に管理。
* 位置など、レイアウトの指定のみ定義
* 子要素は入れない
* 自身のデザインは :open_file_folder: **Project**で定義する


## :page_facing_up: l-wrapper.scss
`body`のすぐ下で、ヘッダーとメインエリアとフッターをかこむ。
コンテンツが少ないとき`footer`を下寄せに指定するのに必要です。

## :page_facing_up: l-header.scss
ヘッダーの位置を定義

## （ :page_facing_up: l-nav.scss)
navは画面構造によって`.p-nav`として`.l-header`のなかに入ることもあるが、`.l-`という大枠のほうがやりやすければLayoutでOKとする。

## :page_facing_up: l-main.scss
メインのコンテンツエリアの**共通スタイル**を定義
* ヘッダーのfixed分の相殺や余白など
* **共通の上下の余白などのみの定義**

## :page_facing_up: l-container.scss
サイトのメインエリア内のコンテンツ幅、左右の余白の指定

## :page_facing_up: l-footer.scss
フッター位置を定義

# :open_file_folder: Object
**パーツやブロックをすべてObject**と定義。
* 小さな単位のパーツを :open_file_folder: Component に。
* Componentが集まったブロックや、大きなエリアは :open_file_folder: Project に。

## :open_file_folder:  Component
**繰り返し使われる小さな単位のパーツ**を管理。
* ネストは**2回**まで
* `margin`など余白は定義しない。あくまでパーツとして扱う

例）
 :page_facing_up: c-button.scss
 :page_facing_up: c-label.scss
 :page_facing_up: c-input.scss
…

## :open_file_folder:  Project
いくつかの  :open_file_folder: Component と要素によって構成される、大きなブロックやエリアを管理。

* `Component`のように使いまわす。
* 使い回さないブロックでも分けて管理したい時。（セクションごとに分けるなど）
* 小さい単位の`Component`を集めて、一つのオブジェクトとして扱いたい時
* Componentとするには大きすぎる時

例）
 :page_facing_up: p-card.scss
 :page_facing_up: p-first-view.scss
 :page_facing_up: p-button-group.scss
…

# :open_file_folder: Utility

* プロパティ単体での指定を補助する。（`font-size`や`margin` `padding`など）
* `Component`、`Project`を無駄に増やしてしまうことを防ぐ
* あくまで補助としての役割。
* `sp only`や`pc only`などレスポンシブの表示切り替え用クラスなど

:page_facing_up: u-margin.scss
:page_facing_up: u-padding.scss
:page_facing_up: u-color.scss
:page_facing_up: u-text.scss

...


# 命名規則

## プレフィックスをつける
:open_file_folder: layout なら`l-`、:open_file_folder: Componentなら`c-`のように、属してるフォルダ名の`{頭文字}`+`-` でプレフィックスを頭につけ、**ファイル名だけでもで判断しやすくする**（Foundationはリセットや下地が目的なので除く）


:page_facing_up: l-header.scss
:page_facing_up: l-footer.scss
:page_facing_up: c-button.scss
:page_facing_up: p-card.scss


## ファイル名 = クラス名
**`l-header.scss`には`.l-header`というクラス名を定義**

## ファイル名、クラス名は省略しない
* 誰が見てもわかるように**ファイル名、クラス名は省略しない**
`txt`や`btn`もNG。**自分で言葉を作らないこと。**（imgはタグ名にあるのでOK）
ただし、`Utility`はクラス名が長くなりがちなので省略可とし、**ファイル名は省略しない**ことで誰が見てもわかるようにする。

## ケバブケース
* `linkbutton`のように繋げず`link-button`のようにケバブケースで書く
* ページ固有のものは`about-card`のようにする


## BEM命名規則`MindBEMding`
BEM命名規則とは**Block、Element、Modifier**に分類して構成される規則。

https://shinkufencer.hateblo.jp/entry/2018/11/05/184131

### Block
* オブジェクト、パーツ、エリアの名前。

### Element
* `BLOCK`の中の要素たち
* `__`でつなげて`.Block__Element`とする
* `.Block__Element__Element`はNG。
* ネストは3階層まで

```html: Element
// NG
<div class="p-about-section">
    ...
    <ul class="p-about-section__list">
        // .Block__Element__ElementはNG
        <li class="p-about-section__list__item">
            <a href="" class="p-about-section__list__item__link">
        </li>
    </ul>
    ...
</div>

// OK
<div class="p-about-section">
    ...
    <ul class="p-about-section__list">
        <li class="p-about-section__list-item">
            // ネストはここまで
            <a href="" class="p-about-section__list-link">
        </li>
    </ul>
    ...
</div>
```


### Modifier
* オブジェクトの色違いやサイズ違いといった一部の見た目が違うとき
* 色名やサイズ名を`--`でつなぎ`.Block--Modifier`のようなかたちにする。
* `.Block--Modifier--Modifier` はNG
* `.Block__Element--Modifier`は`__Element`自体の〇〇違いであればOK

```html:例） .Block--Modifier
<!--ボタン-->
<button class="c-button"></button>
<!--ボタンの色違い＋サイズ違いモディファイア-->
<button class="c-button c-button--blue c-button--small"></button>
```

#### **オブジェクト全体の`Modifier`のときは`$this: &`を使う**
* 子要素の`Element`には`Modifier`はかかないで`Block`だけ`Modifier`にする
* SCSSの`$this: &`で子要素の`Element`にスタイルをあてます

```html:オブジェクト全体のModifier
<div class="p-card p-card--green">
  <div class="p-card__header">
  </div>
  <div class="p-card__body">
  </div>
  ...
</div>
```
```scss:$this: &
.p-card {
    $this: &; // &(p-card)を$this変数にする    
    color: black;
    &__header {
        background-color: gray;
    }
    &__body {
        background-color: white;
    }

    //Modifier
    &--green{
        color: green;  
        #{$this}__header { // .p-card--green .p-card__headerに変換
            background-color: green; 
        }
        #{$this}__body { //.p-card--green .p-card__bodyに変換
            background-color: lightgreen;
        }
    }
}
```


### `Element`単体のみの`Modifier`もOK
* オブジェクトの中の一部の`Element`を右寄せにしたいときなどは`.p-card__label--center`のように`Element`に`Modifier`を指定する
* 2つ以上の`Element`が変わる場合は前項のオブジェクト全体の`Block`にあてる

```html:オブジェクトのなかの要素だけModifier
<div class="p-card p-card--green">
  <div class="p-card__header">
    <div class="p-card__label p-card__label--center">
    </div>
  </div>
  ...
</div>
```
このように分けることでいろんなパターンのオブジェクトを作れる

### ハイフン1つのクラス名は`&-`で書かない
* 下記の例だと`__content`を探すときに一瞬混乱するので推奨しない

```scss:NGの例
.p-card{
    &__content{
    }
    &__head{
        &-content{ //contentがかぶるのでこの書き方は非推奨
        }
    }
}
```
```scss:OKの例
.p-card{
    &__content{
    }
    &__head{
    }
    &__head-content{ 
    }
}
```


## JavaScriptから参照、操作されるクラス名

### キャメルケース`camelCase`
JavaScriptに関連するクラス名はキャメルケース`camelCase`でかく

### JavaScriptから参照されるクラス名
* `.js-modalToggle`のように**プレフィックスに`js-`をつけてJavaScriptで操作されることを明示する。**
* `.js-`のクラス名にはスタイルはあてない
* JavaScriptでは`.js-modalToggle`に処理を与える

### JavaScriptから操作されるクラス名
* **プレフィックスに`is-`をつけ、定義する**
* * JavaScriptでは`.is-click`が操作する処理を与える
* **`is-click`のみにスタイルは定義せず、必ず、`.c-button.is-click`にスタイルを定義する。**（他のオブジェクトに対する`.is-click`にスタイルが当たるのを防ぐ）

```html:JavaScript用のクラス
<button class="c-button js-button is-click"></button>
<div class="p-modal js-modalToggle is-click"></div>
```
同じ`.is-click`というクラス名を使っても別々のスタイルを当てることができる。

# カスケーディングに気をつける
>カスケーディングとは，ある要素のあるプロパティに対する宣言が複数あるとき，宣言の“強さ”の関係を定めて，うち 1 つの宣言だけが有効になるようにするしくみである
[Let's begin CSS \-\- 2\.5](http://www.tg.rim.or.jp/~hexane/ach/lbcs/lbcs2-05.htm)


### 別のオブジェクト同士、別のオブジェクトを親とするセレクタを用いたカスケーディングは禁止

つまり下記のように`Project`を親に持つ別の`Project`にスタイルを定義するのはだめ。

```css:だめな例

// Component
.c-button {
  ...
}
.c-dialog>.c-button { 
  /*c-dialogを親に持つc-buttonのみスタイルを指定してしまってる！ダメ！*/
  ...
}

// Project
.p-comments {
  ...
}
.p-articles>.p-comments { 
  /*p-articlesを親に持つp-commentsのみスタイルを指定してしまってる!そんな書き方ダメ！*/
  ...
}
```
理由として、
>特定のモジュールに依存することなく、モジュールとして独立して再利用できるべきであり、混在させることによって他の開発者が予想しない挙動になるべきではないためです。
抜粋：[hiloki/flocss: CSS organization methodology\.](https://github.com/hiloki/flocss)

つまり、

- **汎用的であるべきパーツ(例：c-button)が他のComponent内でしか力を発揮できなくなるのはおかしい**
- 混在することで第三者に、**どれがもとの`c-button`のスタイルなのか**、**`c-button`なのにここの下では変わってしまう**、**この`c-button`を使いたいのにならない**、といった混乱を招いてはいけない

ということ。

```html:p-cardの例
<div class="p-card">
  <div class="p-card__header">
  </div>
  <div class="p-card__body">
  </div>
  <div class="p-card__footer">
    <a class="c-button" href="/"></a>
  </div>
</div>
```

## `Project`が`Component`を上書きできる

`Component`の集まりをオブジェクトとして`Project`で管理してる場合、余白などの調整は、**`Component`と`Project`の`__Element`を並列して書くことで上書きOKです**

```html:例
<div class="p-profile c-media">
  <img src="user.jpg" class="c-media__image">
  <div class="c-media__body">...</div>
</div>
```
こういったときに、`c-media__image`の余白をどうしても変えたい！となったら

```scss:例
// c-media.scss内
.c-media__image {
  float: left;
  margin-left: 10px;
}

//p-profile.scss内
.p-profile > .c-media__image { //←ここだめ！
  float: right;
  margin-left: 0; 
  margin-right: 10px;
}
```
のように変えるのは**絶対にNG！**
理由は、**`p-profile`内に`c-media__image`があるだけで第三者的には混乱するし、`p-profile`というObjectが成り立たないし、`c-media__image`が`p-profile`のなんなのか、理解しづらいため**


**そのため必ずクラス名を`p-profile`の`Element`ととし、`c-media__image`と並列にかくこと。**

```html:良い例
<div class="p-profile c-media">
  <img src="user.jpg" class="p-profile__avatar c-media__image">
  <div class="c-media__body">...</div>
</div>
```
```scss:良い例
// c-media.scss内
.c-media__image {
  float: left;
  margin-left: 10px;
}

//p-profile.scss内
.p-profile > .p-profile__avatar { //←良い
  float: right;
  margin-left: 0; 
  margin-right: 10px;
}
```

**`Component`のモディファイア（パターン）を増やすことで対応可能な場合はそこで対応すること。**
※ただしモディファイア（パターン）が２つ以上ある場合とする。

## `Project`のなかの`Project`
`Project`のなかの別のオブジェクトである`Project`は並列に書きません。
`Project`は別のオブジェクトによる変更はできません。
※`Project`のなかの`component`のように上書きはしない。
```html:
<div class="p-work-section">
  <h2 class="p-work-section__title c-title"></h2>
  <div class="p-work-section__card-list">
      <div class="p-work-card">
        ...
      </div>
  </div>
</div>
```

## ComponentとProjectの違い
>人間で言えば、裸んぼの人間が最小単位のモジュールcomponentで、他にネクタイや靴下、スーツといったcomponentがあり、組み合わせてビジネスマンprojectになると考えられます
抜粋：[FLOCSSを使ったCSS設計での悩みどころと解決案 \- Qiita](https://qiita.com/uggds/items/d904b2f9a103c37a25fa)

- **小さい単位をComponent**
- **Componentの集まりをProject**
- セクションなどの大きいオブジェクトも`Project`として管理します

### アイコン付きボタンは`.p-button`と`.c-button`を並列にする

```html:例
<a class="p-button p-button--icon c-button" href="/">
  <img src="icon-arrow.jpg" class="c-icon c-icon--arrow">
  <span>お問い合わせ</span>
</a>
```

:::note warn
わかりやすくて気に入ってたんだけど、`.c-icon`は`.p-button`でしか使わないので、この方法はあまり使わなかった。（管理画面のコーディングでは使えるかも）
やってみたら`.p-`にも`.c-`にも`button`がいるのはちょっとムズムズしたので今はあまり使ってません。
:::

結局画像でやるのが楽
```html:結局これでいけちゃう
<a class="c-button c-button--icon" href="/">
  <img src="icon-arrow.jpg" class="c-button--icon__unit">
  <span class="c-button--icon__text">お問い合わせ</span>
</a>
```




# `@extend`は使用しない

例えば、`.c-button`のModifierをつくるには、下記のように**一つのタグへModifierのクラスもつける必要がある**

```html
<!--ボタン-->
<button class="c-button"></button>
<!--ボタンの色違いモディファイア-->
<button class="c-button c-button--blue"></button>
```

`@extend`で`c-button`を継承し、タグへの記載は`c-button--blue`クラスのみ**にすることが出来る。

```scss:SCSS
.c-button {
  ...
}
.c-button--blue {
  @extend .c-button;
  background-color: blue;
}
.c-button--small {
  @extend .c-button;
  background-color: red;
}
```
```css:CSS
.c-button, .c-button--blue, .c-button--red {
  width: 100px;
}

.c-button--blue {
  background-color: blue;
}
.c-button--small {
  width: 80px;
}
```
`c-button--blue`のクラスのみで良いのでクラスの数が減るが、複数の`modifier`を指定するときに、結局`c-button`のスタイルを二重指定してしまうことになるので`@extend`は基本的に使用せず、`c-button`自体も指定します。
```html:HTML
<a class="c-button--blue" href="">
<a class="c-button--blue c-button--small" href="">
```

:rolling_eyes:

# 更新履歴
★2022/04/19　更新
約3年FLOCSSを使い倒し体の一部となった私のためのFLOCSS、編集し直しました。
★2022/08/19
自社のコーディングルール見直しついでに修正しました
# 参考記事

## FLOCSS生みの親による基本ルール

https://github.com/hiloki/flocss


## ComponentとProjectの違い

https://qiita.com/uggds/items/d904b2f9a103c37a25fa

## 命名規則

https://www.tam-tam.co.jp/tipsnote/html_css/post10205.html

## BEM
https://qiita.com/usagi-f/items/b4e56e765384c49d5d04

## クラス名に迷ったら

https://qiita.com/manabuyasuda/items/dbb76ed36970bec95470

https://qiita.com/pugiemonn/items/eaa597b79fe59a1f1506

https://9elements.com/bem-cheat-sheet/