はじめに
この記事ははじめてのCSS設計の記録【検討編】からの続きとなっています。
初めてCSSの設計を行った記録になります。改善できる部分はまだまだあるかと思いますので、都度振り返りを行い定期的にアップデートをしていきたいと思います。
はじめてのCSS設計
基本設計:PRECSS
命名規則:MindBEMding
MindBEMding(マインドベムディング)とは
BEMをCSSのクラス名に適用するために作られた規則のことです。CSSの話をしている時はMindBEMdingがBEMと呼ばれることが多いそうです。つまり、「CSSはBEMを使おう」→「CSSのクラス名はBEMのMindBEMdingに従って命名しよう」と変換することができます。
CSSのカテゴライズ
- ベース
- レイアウト
- モジュール
- ユニーク
- ヘルパー
- プログラム
基本的にはPRECSSの設計をそのまま使用しています。各グループをそれぞれファイルに分けて管理しています。公式との差異は①モジュールに接頭辞をつけないこと、②モジュールをブロックとエレメントにファイル単位で分割しないことの2点です。
1. ベース
配置内容:HTML要素、標準スタイル、リセットCSSなど
接頭辞:なし
ベースにはプロジェクトの標準となるスタイルや、リセットCSSを配置します。ほとんどをHTML要素に対してスタイリングしています。今回、リセットCSSにはブラウザ間の統一は図るけど要素の役割の全てを壊したくないという考えからNormalize.cssを適用しました。
更に細かく分けて管理したい場合、PRECSSではオリジナルのグループを作成することができる柔軟な設計になっているので、リセットCSSを新規のグループに分けて配置するのがいいでしょう。
2. レイアウト
配置内容:ヘッダー、メインエリアなどの大きなレイアウトを形成する要素
接頭辞:ly_
レイアウトにはヘッダー、メインエリア、フッターなどの要素を配置します。メインエリアの中が2カラムであれば、更にコンテンツエリアとサイドエリアなどに分けていきます。画面ごとにレイアウトが異なる場合はその都度枠組みとなるスタイルを追加していく必要があるでしょう。
他の開発者がHTMLを見た時、ly
の接頭辞がついているクラス名をみて、このクラスがレイアウトを形成しているから自分が今から開発しようとしている画面にも適用しよう、という風に判別がつきやすくなっています。
3. モジュール
配置内容:再利用性のあるコンテンツ
接頭辞:なし
モジュールには再利用性のあるスタイルを配置します。モジュールとは、コンポーネントとも言い換えることができ、特定のエリアに依存せずどこでも使用が可能なもの
となっています。特定のエリアに依存せず、とはモジュールが他のスタイルが適用されている要素下でもデザインの崩れがない状態を指します。
PRECSSのモジュールにはブロックモジュール
とエレメントモジュール
に分けられていますが、BEMを使用したいと思い今回は統一しています。
更に、接頭辞がありませんが、これは接頭辞なしのクラス名はモジュールグループと判断することができ、あまりクラス名が長くならないようにと考え、つけない方針にしました。
モジュールにはBEMの命名規則を適用します。
BEMとはBlock
、Element
、Modifier
の略で、それぞれ以下のように定義されています。
Block:どこでも使い回せるパーツ
Element:Blockの構成要素、Blockの中でしか機能しないもの
Modifier:BlockやElementの修飾を定義するもの
記法は以下のようになっており、Elementはアンダースコア2つ(__)、Modifierはハイフン2つ(--)で連結するようにします。
block
block__element
block__element--modifier
block--modifier
block--modifier__element
エレメントの下層にエレメントが来るパターンもあるかと思いますが、その場合もエレメントを2つ繋げずに、block__element
の記法で問題ありません。ブロックが一意になっている想定なので、エレメントを重ねて命名する必要がないためです。
ElementやModifierを定義するとき必ず先頭にBlockになりクラス名が長くなりがちですが、これはどのブロックに対してなのかがわかる
やみだりに影響範囲を広げない
といった目的があります。BEMを適用する際、後述するSass
を使用することで効率よく開発することができますのでぜひ取り入れましょう。
4. ユニーク
配置内容:ある特定の場所でしか使用していないスタイル
接頭辞:un_
特定の場所でしか使用していないので、影響範囲がなく後からの修正が容易です。ただ、あまり乱用すると再利用性がなくなってしまうので、ユニークに配置するときはモジュールに配置できないか一旦検討してみるのがいいと思います。
ユニークグループに配置したスタイルには、どの画面で使用しているかそれぞれコメントを残すようにします。
5. ヘルパー
配置内容:単一のスタイルなど
接頭辞:hp_
marginやpaddingなど、ある部分だけを調節したいとなった場合に適用するスタイルを配置します。BootStrapのmt-0
のようなクラスを定義するイメージです。
6. プログラム
配置内容:JSなどでHTML要素を取得する際にセレクタとなるクラス、状態を管理するクラスなど
接頭辞:js_ または is_
JSで要素に対して何か操作をする際に、接頭辞の「js_」を付けたクラスをセレクタとして扱います。また、状態の管理は接頭辞「is_」を使用し、例えばis_active
というクラスにdisplay: block
などを当てる、といったようにスタイルを適用します。
開発手順
【使用するもの】
- Fractal:スタイルガイドジェネレーターの1つ。プロジェクト内のモジュールを一元管理することができる(公式サイト)
- Sass(LibSass):CSSメタ言語。今回はnode-sassライブラリでSassを使用する(公式サイト)
- gulp:様々な処理を自動化するツール。Sassのコンパイル時に使用する(公式サイト)
開発において使用するツールや言語です。
詳しい説明はそれぞれ公式サイトをご確認ください。
【事前準備】
-
fractal.config.jsがあるディレクトリで
fractal start --sync
→command not foundの場合-
../node_module/.bin/fractal start --sync
または npm i -g @frctl/fractal && fractal start --sync
-
-
gulpfile.jsがあるディレクトリで
gulp sass:watch
→command not foundの場合-
node_module/.bin/gulp sass:watch
または npm i -g gulp-cli && gulp sass:watch
-
開発の前に2つのコマンドを入力しそれぞれ起動させておいてください。
fractalの方はfractal.config.jsを配置しているディレクトリ内のドキュメントやコンポーネントが保存された時、gulpの方はscssファイルが保存された時、それぞれ自動で更新がかかるようになっています。
【手順】
- Fractal上で利用できそうなモジュールを検索する
- 該当するモジュールが存在する場合はそのまま使用する
- 存在しない場合はFractalにモジュールのHTML側を作成する
- Sassでスタイリングする
- gulpでscssファイルをコンパイルする
- Fractalでモジュールの確認をする
- 実際のHTMLファイルにモジュールを適用する
1. Fractal上で利用できそうなモジュールを検索する
Fractalはスタイルガイドジェネレーターの1つです。スタイルガイドとはUIパーツやプロジェクト内のテーマをまとめておき、デザインの現物をそのまま確認することできるので、他の開発者が後から見た時に自分の使うべきクラスの見通しが立ちやすくなります。
まずはこのFractal上で、自分が利用したいモジュールがないか確認します。
2. 該当するモジュールが存在する場合はそのまま使用する
利用できそうなモジュールがあった場合は、下のHTML
タブで適用されているクラス名を確認して実際のHTMLファイルに記述します。
例でいうと、標準ボタン
モジュールを使用したいので、HTML
タブを見てbtn
クラスを確認し、HTMLファイルに適用する、といった流れになります。
3. 存在しない場合はFractalにモジュールのHTML側を作成する
利用できそうなモジュールがない場合は自分で新規作成する必要があります。このとき、後のこと考えてまずはFractal上でモジュールを作成していきます。
以下は、Fractalのディレクトリ構成となっています。
styleguide
という名前でなくても問題ありません。
components:各モジュールを配置します
docs:ドキュメントを配置します
fractal.config.js:fractalの設定ファイルです
components
ディレクトリにはHTML側を実装していきます。初期設定ではhandlebars
になっていますが、今回はpug
を使用します。pugに変更する場合はfractal.config.js
で設定することができます。
components
ディレクトリには更にディレクトリを切っていますが、これはなくても問題ありません。一応大きなコンポーネントの括りで分けています。
以下の例では、Button
のディレクトリの中にDefault
とOutline
が存在しています。
これはstyleguide
ディレクトリでbutton
ディレクトリを切ったからではありません。ファイル名によってこうしたディレクトリ構成になっています。
このように、button.pug
とModifierであるbutton--outline.pug
がありますが、Fractalではハイフン2つを連結させることで、そのファイルをデフォルトのモジュールに対しての変化系として認識させることができます。
ちょうどBEMのModifierと同じ命名方法だったのでそのまま使用することにしました。
長くなりましたが、最後にbutton.pugの中身を見てみましょう。
a.btn(href='#') 標準ボタン
hr
a.btn(href='#') テキストが長い場合は折り返される標準ボタン
hr
.btn divタグの標準ボタン
ボタンモジュールなのでとても単純なので、複合モジュールのようなエレメントがたくさん入れ子になっているものだともっと複雑なものになるかと思います。
今回button.pugとしては1行目のコードだけで十分だったのですが、念の為Modifierまではいかないけど、そのモジュールの変化型をまとめておきたいと思い、hr
タグの線で区切って複数パターンを表示させています。
他の開発者がFractalを使ってモジュールを見た時、このHTML要素で.btn
クラスを使用すれば画面に表示されているボタンが使用できることを認識でき、再利用されてコードの重複を抑えることに繋がります。
4. Sassでスタイリングする
先程のボタンモジュールには.btn
クラスを当てていました。このクラスに対してSassを使用してCSSの実装を行います。
なぜSassを使用するのかというと、PRECSSの6つのグループごとにファイルを分けたかったというのが理由になります。
CSSのままファイルを分けてしまうと、全てのファイルを1つずつ読み込む必要があり、微小ながらパフォーマンスに影響が出てしまいます。
Sassはコンパイルする時に複数のscssファイルを1つのCSSファイルにまとめることができ、読み込みも1つのファイルで済むことができます。
ディレクトリ構成は以下のようになっています。
sass
ディレクトリ直下にstyle.scss
、_utiles.scss
、categories
ディレクトリが配置されています。
categories
にはPRECSSの6つのグループがファイルごとに分けられています。
style.scss
以外のファイル名の先頭にアンダースコアが付いていますが、これはコンパイル時にファイルが生成されないようにするためです。では、そのファイルの中身はどのようにCSSとして出力されるかというと、style.scss
の中身を見ることでわかります。
@import 'categories/base';
@import 'categories/layout';
@import 'categories/module';
@import 'categories/unique';
@import 'categories/helper';
@import 'categories/program';
ファイル名にアンダースコアが付いたCSSファイルを出力しないscssファイルをパーシャルファイルと言いますが、このパーシャルファイルをstyle.scss
で全てインポートすることで内容を一つにまとめ、style.css
として出力することができます。
この時、インポートしたファイルの順番通りにCSSの中身も出力されるので、下の方にインポートしたscssファイル程優先度が高くなります。なので、自分は上書きが起きてほしいグループ程下にインポートするようにしているので、この辺は特にオリジナルグループを作成した時は、各自調整してみてください。
またまた長くなりましたが、最後に.btn
のスタイリングですが、今回は_module.scss
ファイルに記述していきます。
.btn {
display: inline-block;
width: 300px;
max-width: 100%;
padding: 6px 10px;
background-color: #004E98;
border: 2px solid transparent;
border-radius: 5px;
box-shadow: 0 3px 6px rgba(0, 0, 0, .16);
color: #fff;
font-size: 1.125rem;
text-align: center;
text-decoration: none;
transition: .25s;
&:focus,
&:hover {
background-color: #fff;
border-color: currentColor;
color: #004E98;
}
&--outline {
background-color: #fff;
border-color: #004E98;
color: #004E98;
&:focus,
&:hover {
background-color: #004E98;
border-color: transparent;
color: #fff;
}
}
}
5. gulpでscssファイルをコンパイルする
今回はgulpの設定で、ファイルを保存するとコンパイルしてくれるようにしています。
以下は出力されたCSSです。
.btn {
display:inline-block;
width:300px;
max-width:100%;
padding:6px 10px;
background-color:#004e98;
border:2px solid transparent;
border-radius:5px;
box-shadow:0 3px 6px rgba(0,0,0,.16);
color:#fff;
font-size:1.125rem;
text-align:center;
text-decoration:none;
transition:.25s
}
.btn:focus, .btn:hover {
background-color:#fff;
border-color:currentColor;
color:#004e98
}
.btn--outline {
background-color:#fff;
border-color:#004e98;
color:#004e98
}
.btn--outline:focus, .btn--outline:hover {
background-color:#004e98;
border-color:transparent;
color:#fff
}
.btn
に対して.btn--outline
という枠線のみのボタンを表示させるModifierを用意しました。
SassはBEMととても相性が良く、scssの記述量が少なく済んでいるのが出力結果からわかるかと思います。
スタイリングが完了しましたので、後はFractalで実際のデザインを確認し、HTMLファイルへの方へ反映させて一連の流れが完了となります。
普通にCSSを書いて実装するより、時間が多少かかるかと思いますが、管理や他の開発者への共有のことを考えると時間をかけるべき工程だと思っています。
以上となります。
ありがとうございました。
参考
2018年の終わりに改めてgulpでsass(scss)をコンパイルする【決定版】
fractal のテンプレートをpugにする
Fractalを使ったスタイルガイドの作成(中級編)