吉本式BEM設計(BEM設計ベース)

美しいコーディングをするためのガイドラインコンテンツです。

SCSSのファイル設計について Vol.1

SCSSのファイル設計について、解説します。
ディレクトリ構造は次のようなテンプレートとなります。

- scss
  - base
  - mixin
  - module
  - page
  - pulgins
  - setting
  style.scss

それぞれのディレクトリの役割は、次のようになります。

baseディレクトリ
ベースとなるスタイルが定義さているSCSSファイルを格納するディレクトリです。

mixinディレクトリ
mixinが定義されているSCSSファイルを格納するディレクトリです。

moduleディレクトリ
サイト共通で使用するモジュール別にスタイルが定義さているSCSSファイルを格納するディレクトリです。

pageディレクトリ
ページ単位で使用するスタイルが定義さているSCSSファイルを格納するディレクトリです。

pulginsディレクトリ
外部プラグインのスタイルを格納するディレクトリです。

settingディレクトリ
初期設定で必要なパラメータなどが定義されているSCSSファイルを格納するディレクトリです。

scssディレクトリ直下にあるstyle.scssは、サイト共通のモジュールや設定ファイルをインポートするSCSSファイルになります。
それでは、具体的にどのようなファイルが格納されているか解説します。

baseディレクトリ

baseディレクトリは、ベースとなるスタイルが定義さているSCSSファイルを格納するディレクトリです。
必要な具体的なファイルは、次になります。

- scss
  - base
    _base.scss
    _reset.scss
  - mixin
  - module
  - page
  - pulgins
  - setting
  style.scss

まずは、_reset.scssですが、これはスタイルをリセットするファイルです。
リセットCSSについては解説する必要はないと思いますので、割愛します。
続いて、_base.scssですが、このSCSSファイルにはサイト共通で設定する必要のあるスタイルを定義します。
例えば、次のようなスタイルです。

body{
  color: #000;
  font-family: フォント名;
}
//SP
@media screen and (max-width: #{nth($breakPointList, 1)}){
  body{
    min-width: 320px;
  }
  html, body{
    height: 100%;
    min-height: 100%;
  }
}
//PC
@media print,screen and (min-width: #{nth($breakPointList, 2)}){
  body{
    width: 100%;
  }
}

_base.scss, _reset.scssのファイルでは、基本的にはタグ指定でスタイルを指定します。
BEM設計での指定は、ここではしません。
HTML上で設定するクラスは、BEM設計によるBlock、Element, Modifier以外は、基本的には出てきません。
ただし、例外が2つあります。

1つは、JavaScriptで使用するためのタグを指定するためのクラス設定です。
例えば、次のようなソースコードがあったとします。

<nav class="gnav">
<ul class="gnav-list">
<li class="gnav-item"><a href="#"></a></li>
<li class="gnav-item"><a href="#"></a></li>
<li class="gnav-item"><a href="#"></a></li>
</ul>
</nav>

上のソースコードで、li要素に対し、JavaScriptで何かしらの設定が必要になった場合、次のようなクラスを設定します。

<nav class="gnav">
<ul class="gnav-list">
<li class="gnav-item js-gnav-item"><a href="#"></a></li>
<li class="gnav-item js-gnav-item"><a href="#"></a></li>
<li class="gnav-item js-gnav-item"><a href="#"></a></li>
</ul>
</nav>

JavaScriptで使用するために設定するクラス名は、

'js' + '-' + 'クラス名'

とします。
このケースが、BEM設計によるBlock、Element, Modifier以外に出てくるクラス名の1つ目です。

2つは、少々苦肉の策になってしまいますが、Block、ElementのないModifierです。
私は、このクラスを1パターンのみ使用しています。
これは、BEM設計の概念から外れてしまうケースですので、極力使用しません。
唯一、必要になってしまうのが、レスポンシブサイトによるPCレイアウト時には非表示、SPレイアウト時には非表示にする・・・というクラスです。
これをそれぞれ_pc, _spというクラス名にしてスタイルを設定しています。
具体的には次のようなスタイルです。

//SP
@media screen and (max-width: #{nth($breakPointList, 1)}){
  ._pc{
    display: none;
  }
}
//PC
@media print,screen and (min-width: #{nth($breakPointList, 2)}){
  ._sp{
    display: none;
  }
}

このクラス設定が必要ないというのが理想になりますが、実務案件ではどうしても必要になってしまうケースがあります。
このケースが、BEM設計によるBlock、Element, Modifier以外に出てくるクラス名の2つ目になります。
この2つ目の_pc, _spクラスに関しては、_base.scssに定義することになります。

mixinディレクトリ

mixinが定義されているSCSSファイルを格納するディレクトリです。
SCSSで実装する際に、どのような時にmixinを定義して使用するか、と悩むと思います。
これを明確にし、ルールを設けることで、悩むことはなくなります。

mixinルール 1
別Blockで同じスタイルが必要になった場合、mixinを定義する。

よく出てくるケースとして、サイト内で共通して使用されるボタン系です。
例えば、サイト共通のヘッダーと、コンテンツに共通のボタンが出てくる場合を見てみます。
まずはHTMLのソースコードから。

<header class="header">
<p class="header-btn"><a href="#">サイト共通ボタン</a></p>
</header>

<section class="sec">
<p class="sec-btn"><a href="#">サイト共通ボタン</a></p>
</section>

吉本式BEM設計(BEM設計ベース)では、見やすいSCSS設計を考慮し、1つのBlockに対し、必ずそのBlockの対になるSCSSファイルを用意する。
というルールを定めています。
これについては、後ほど解説します。
そのため、次のようなスタイルの設定はしません。

.header, .sec{
  &-btn{
    //サイト共通ボタンのスタイル
  }
}

よって、mixinでの定義になります。

@mixin _btn{
  //サイト共通ボタンのスタイル
}
.header{
  &-btn{
    @include _btn;
  }
}
.sec{
  &-btn{
    @include _btn;
  }
}

mixinの定義ファイルは、細かく分けます。
上のサイト共通ボタンで、1つのmixinの定義ファイルとします。
理由としては、1つのmixinの定義ファイルに、必要なmixinの定義を書いてしまうと、結構なコード数になってしまい、どこに何が書いてあるのかわからなくなってしまうからです。

mixinルール 2
1つのmixinに対し、1つの定義ファイルを用意する。
mixinルール 3
mixinの定義ファイル名は、mixin名と同じにする。

このルールを定めることで、見やすい・わかりやすいSCSS設計になります。
上の例は、mixin名が_btnなので、ファイル名も_btn.scssとなります。
もし、サイト共通ボタンが複数パターンが出てくる場合は、次のように分岐します。

$initType: 'normal';
@mixin _btn($type:$initType){

  //共通スタイル

  //サイト共通ボタンのスタイル 1
  @if( $type == 'normal' ){
    //スタイル
  }

  //サイト共通ボタンのスタイル 2
  @else if( $type == 'large' ){
    //スタイル
  }

}
.header{
  &-btn{
    @include _btn;
  }
}
.sec{
  &-btn{
    @include _btn('large');
  }
}

実務経験上、mixinの定義ファイルはそれなりに複数必要になってきます。
よく出てくる定義ファイルとして、フォント系の_font.scss、アニメーション系の_animation.scss、要素オーバー時の設定ファイルの_over.scss、これらは頻繁に必要になります。

- scss
  - base
    _base.scss
    _reset.scss
  - mixin
    _btn.scss
    _font.scss
    _animation.scss
    _over.scss
    _etc.scss(その他)
  - module
  - page
  - pulgins
  - setting
  style.scss

moduleディレクトリ

サイト共通で使用するモジュール別にスタイルが定義さているSCSSファイルを格納するディレクトリです。
moduleディレクトリに格納されるSCSSファイルは、必ずBEM設計のBlock単位になります。
また、サイト共通で使用するモジュール(Block)となりますので、次のBlockは基本的にどの案件でも出てくるモジュールとなります。

サイト共通ヘッダー : _header.scss
サイト共通フッター : _footer.scss
メイン : _main.scss
コンテンツ : _content.scss
サイドメニュー(サイドコンテンツ) : _snav.scss(_side.scss)
グローバルメニュー : _gnav.scss
フッターメニュー : _fnav.scss
シェアエリア : _share.scss

Webサイトによっては必要ないBlockもあるかと思いますが、基本的な大枠のアウトライン要素として、HTMLのソースコードは次のようになります。

<!-- header -->
<header class="header">
サイト共通ヘッダー
</header><!-- /header -->

<!-- gnav -->
<nav class="gnav">
グローバルメニュー
</nav><!-- /gnav -->

<!-- main -->
<main class="main">

<!-- content -->
<div class="content">
コンテンツ
</div><!-- /content -->

<!-- snav -->
<nav class="snav">
サイドメニュー
</nav><!-- /snav -->

</main><!-- /main -->

<!-- footer -->
<footer class="footer">
サイト共通フッター

<!-- fnav -->
<nav class="fnav">
フッターメニュー
</nav><!-- /fnav -->

</footer><!-- /footer -->

これらの大枠のアウトライン要素(Block)は、サイト共通になりますので、moduleディレクトリに格納されるモジュールとなり、それぞれのBlock名でSCSSファイルを生成します。

- scss
  - base
    _base.scss
    _reset.scss
  - mixin
    _btn.scss
    _font.scss
    _animation.scss
    _over.scss
    _etc.scss(その他)
  - module
    _header.scss
    _gnav.scss
    _main.scss
    _content.scss
    _snav.scss
    _side.scss
    _footer.scss
    _fnav.scss
    _share.scss
    _etc.scss(その他)
  - page
  - pulgins
  - setting
  style.scss

moduleディレクトリに格納されるSCSSファイルのルールは、基本的にはmixinディレクトリと同じです。

moduleルール 1
1つのBlockに対し、1つの定義ファイルを用意する。
moduleルール 2
SCSSファイル名は、'_' + 'Block名'と同じにする。

吉本式BEM設計(BEM設計ベース)のSCSSファイル名のルールとして、次のルールがあります。

SCSSファイル名ルール 1
importされるSCSSファイルには、頭に '_' を付ける。

これまでできたbaseディレクトリ、mixinディレクトリ、moduleディレクトリに格納されるSCSSファイルは、全てimportされるSCSSファイルになりますので、全てファイル名には、頭に'_'が付与されることになります。
頭に'_'が付与されていないSCSSファイルは、CSSファイルに出力されるファイルとなりますので、このSCSSファイル名のルールがあれば、どのSCSSファイルがimport用で、どのSCSSファイルがCSSファイルに出力されるファイルなのかがファイル名から判断できるようになります。

記事が長くなってしまいましたので、残りのディレクトリの解説は次の記事で解説します。