SCSSのファイル設計(クラス名の命名規則と要素について vol.1)
FLOCSS設計の命名規則では、要素を区別するため、次のようにクラス名にプレフィックスをつけることが推奨されています。
Layout要素 → l-* 例)l-header
Component要素 → c-* 例)c-btn
Project要素 → p-* 例)p-profile
吉本式ではクラス名にプレフィックスの採用をやめました。
クラス名を極力短くしたい。
プレフィックスをつけなくても要素を見れば区別の判断ができる。
という理由です。
上の例を、吉本式にすると次のようになります。
Layout要素 → header
Component要素 → btn
Project要素 → profile
プレフィックスがなければ、要素の区別がなく、分かり難い。
一見そう思われそうですが、FLOCSS設計のルールを厳格化することで、クラス名ではなく、その要素がどのような要素なのかで区別を判断することができます。
これについてはこれから解説していきます。
プレフィックスがなければ、FLOCSS設計じゃないじゃん。
もしかするとそう判断してしまう人もいるかもしれません。
吉本式ではFLOCSS設計の考え方が最も重要なのであって、命名規則やディレクトリ構成は重要ではないと考えています。
これから各要素について解説していきますが、FLOCSS設計の考え方の知識があるということを前提として解説していますので、もしFLOCSS設計の知識がなければ、まずは一度FLOCSS設計の知識を勉強してから読んでいただければと思います。
また、吉本式では、FLOCSS設計の考え方を基にルールを厳格化し、コーディング作業における「迷い」を軽減することが目的で新たに考えた設計ですので、FLOCSS設計と比較するものではありません。
Layout要素
サイト共通となるBlock定義をLayout要素としますが、具体的には、レイアウトの大枠となる要素となり、該当する要素は限定的です。
header(header要素) ・・・ ヘッダー
footer(footer要素) ・・・ フッター
main(main要素) ・・・ メインコンテンツ
side(div要素) ・・・ サイドコンテンツ
container(div要素) ・・・ コンテナ
wrap(div要素) ・・・ ラップ
経験上、上の要素以外にLayout要素が出てくることは基本的にはありません。
もし上記以外に出てきたとしても、レイアウトの大枠の要素になりますので判断できます。
これらをマークアップの要素でルール化すると、次のようなルールができます。
- Layout要素ルール
- Layout要素になりうる要素は、header要素, footer要素, main要素または、div要素のみとする。
header要素、footer要素を複数使用するという考え方の実装者もいるかと思いますが、私のマークアップの場合、header要素、footer要素はサイト共通のヘッダー、フッターにしか使用しません。
そのため、1ページ内のソースコードに出てくるheader要素、footer要素そして、main要素は必ず1つになり、これらは必ずLayout要素になります。
div要素がLayout要素になるケースは、header要素、footer要素そして、main要素の外にdiv要素がある場合のみです。
これに該当するのが、サイドコンテンツ(side)とコンテナ(container)になりますが、もしかすると、デザインによってはさらに別のコンテナ要素などが必要になるかもしれません。
そういうケースになった場合でも、それらの要素が、header要素、footer要素そして、main要素の外にあるのであれば、Layout要素となりますので、迷うことはありません。
- html
-
<body>
<header class="header">ヘッダーコンテンツ</header>
<main class="main">メインコンテンツ</main>
<footer class="footer">フッターコンテンツ</footer>
</body>
header要素、main要素、footer要素のみで構成されたシンプルなマークアップです。
それぞれの要素の中には、Project要素、Component要素が構成されますが、これらの要素の大枠として構成されているのでLayout要素になります。
続いて、サイドコンテンツが必要になった場合は、次のようなマークアップになります。
- html
-
<body>
<header class="header">ヘッダーコンテンツ</header>
<div class="container">
<main class="main">メインコンテンツ</main>
<div class="side">サイドコンテンツ</div>
</div>
<footer class="footer">フッターコンテンツ</footer>
</body>
side要素とcontainer要素が追加されましたが、これらはmain要素の外にありますので、Layout要素として判断することができます。
この他に考えられるケースとして、次のようなマークアップが必要になるかもしれません。
- html
-
<body>
<div class="wrap">
<div class="wrap_inner">
<header class="header">ヘッダーコンテンツ</header>
<div class="container">
<main class="main">メインコンテンツ</main>
<div class="side"></div>
</div>
<footer class="footer">フッターコンテンツ</footer>
</div>
</div>
</body>
上のようなケースだったとしても、wrap要素は、header要素、footer要素、main要素の外に配置されているdiv要素ですので、Layout要素になるという判断ができます。
wrap要素の中にさらにdiv要素などが必要になった場合(wrap_inner要素)は、wrap要素のElement要素として、区別することができます。
いかがでしょうか、このルールに従えば、Layout要素の判別は明確ですので「クラス名にプレフィックスをつける必要はない」という判断です。
Component要素
再利用できる最小の単位のモジュールをComponent要素とします。
具体的に挙げると、テキスト、ボタン、画像、リスト、見出し、入力項目・・・などなどになり、これらをタグにすると、p要素、button要素、figure要素、h要素、input要素・・・などなどになります。
ただし、これらが必ずComponent要素になるとは限りません。
Layout要素またはProject要素のElement要素になる場合もあります。
Component要素とElement要素の判別は、再利用できるかどうかです。
また、Component要素とはなり得ない要素を決めておきます。
section要素、article要素、nav要素、aside要素、form要素またはdiv要素に関しては、最小の単位のモジュールになるとは考えにくいため、Component要素にはなりません。
strong要素、em要素などの装飾要素に関しては、単独で使用することはなく、何かしらのComponent要素、またはElement要素に依存するはずですので、Component要素にはなりません。
さらに特殊なケースとして、
Component要素にはしたくないが、Component要素として使用する場合のある要素、Component要素としてのみ使用したいが、Project要素としても使用しなければならないケースがある要素が出てきてしまいます。
Component要素にはしたくないが、Component要素として使用する場合のある要素
span要素がこれにあたります。
Component要素にはしたくない理由としては、span要素は自身では意味を持たない要素だからです。
ただし、実務上、Component要素として使用しなくてはいけないケースが出てきます。
例えば、基本的にはボタンとして使用していた形状(スタイル)が、イレギュラーとしてボタンの形状のままボタンの機能を持たない要素が必要になるケースがあり、その場合はbutton要素からspan要素に変更せざるを得ません。
この場合、span要素はComponent要素になります。
- html
-
<button class="btn">ボタンです</button>
<span class="btn">ボタンの形状だけど、ボタンではない</span>
上のようなマークアップになってしまうケースが、ごく稀ですが実務では出てきます。
その他にも、span要素をComponent要素として使用せざるを得ないケースが出てきますので、これは許容します。
Component要素としてのみ使用したいが、Project要素としても使用しなければならないケースがある要素
a要素がこれにあたります。
a要素は基本的にはリンク要素ですので、Component要素としてのみ使用したいです。
- html
-
<a class="link">リンクテキスト</a>
ただ、実務では「このブロックを丸っとリンクエリアにしたい。」という要望をディレクターやデザイナーから受けることがあります。
例えば、次のようにマークアップをしていたとします。
- html
-
<div class="item">
<figure class="item_pic">
<img src="xxx.jpg">
</figure>
<p class="item_title">タイトルテキスト</p>
<a href="#" class="item_link">リンクテキスト</a>
</div>
上のマークアップでは、a要素をElement要素として使用していますので、問題ありません。
この状態からブロック(item要素)を丸っとリンクエリアにしなければいけなくなった場合、次のようなマークアップになります。
- html
-
<a href="#" class="item">
<figure class="item_pic">
<img src="xxx.jpg">
</figure>
<p class="item_title">タイトルテキスト</p>
<p class="item_link">リンクテキスト</p>
</a>
丸っとリンクエリアにすると、上のようなマークアップになり、a要素をProject要素として使用せざるを得えません。
これらのケースが出てきますので、span要素とa要素に関しては、許容しますが、明確な理由がありますので、「迷い」には繋がらないと思っています。
Component要素のルールをまとめます。
- Component要素ルール 1
- 再利用できるモジュールをComponent要素とし、再利用できない要素はElement要素となる。
- Component要素ルール 2
- section要素、article要素、nav要素、aside要素、form要素またはdiv要素は、Component要素にはなり得ない。
- Component要素ルール 3
- strong要素、em要素などの装飾要素は、Component要素にはなり得ない。
これらのルールから、Component要素になり得る要素をまとめると、
p, h(x), figure, ul, ol, button, a, span, input, select, textarea, table, dl
上のhtml要素がComponent要素になり得る要素です。
Component要素のクラス名に関してですが、Component要素は「最小の単位のモジュール」ですので、そのモジュール名がクラス名になります。
いくつか例を挙げると
見出し(h要素)・・・ heading
ボタン(button要素)・・・ btn
リスト(ul要素, ol要素)・・・ list
テキスト(p要素)・・・ text
リンク(a要素)・・・ link
写真(figure要素)・・・ pic
動画(figure要素)・・・ movie
定義リスト(dl要素)・・・ dlist
表組み(table要素)・・・ table
などなどです。
案件によってたくさんのComponent要素が出てくると思いますので、可能な限りモジュール名が想像できるクラス名にすることを推奨します。
Project要素
いくつかのComponent要素とElement要素で構成された要素がProject要素です。
FLOCSS設計では「Layout要素なのかProject要素なのか」というのが迷うポイントの1つですが、Layout要素さえしっかりルールを決めておけば、大丈夫なはずです。
Layout要素になりうる要素は、header要素, footer要素, main要素または、div要素のみとする。
と、ルールを設けました。
section要素、article要素、nav要素、aside要素、form要素またはdiv要素は、Component要素にはなり得ない。
と、ルールを設けました。
また、a要素をProject要素として使用せざるを得えないケースもあることを解説しました。
これらのルールから、Project要素には次のルールを設定できます。
- Project要素ルール
- Project要素になりうる要素は、section要素、article要素、nav要素、aside要素、form要素またはdiv要素、a要素のみとする。
Block要素(Layout要素、Component要素、Project要素)のクラス名の命名規則について
これらの要素は、BEM設計でいうところのBlock要素になりますので、Block名になると考えてください。
header要素(Layout要素)であればheaderクラス、btn要素(Component要素)であればbtnクラス、section要素(Project要素)であればsecクラス。
Block名にハイフン(-)、アンスコ(_)を付けることや、キャメル方式にすることはNGとしています。
クラス名が長くなること、見た目が悪いことが理由です。
- Block要素のクラス名の命名規則ルール
- ハイフン(-)、アンスコ(_)を付けることや、キャメル方式にすることは禁止する。
このルールについては、Block要素以外にも、Element要素やModifierにも適用します。
例えば、グローバルナビのクラス名を例に挙げると、
global-nav
global_nav
globalNav
などが考えられるかもしれませんが、吉本式では、
gnav
とします。
これだけではわからないかもしれませんので、グローバルナビのElement要素で見てみます。
global-nav_title
global_nav-title
globalNav_title
gnav_title
Element要素のクラス名ではどうでしょうか。
もちろん、色々な意見があると思います。
・クラス名は長くても特に気にならない。
・省略されると何のクラスなのかわかりにくい。
というような意見が出ることが想定できますが、いずれにしても間違いではありません。
どういう命名規則になっているかが統一されていることが重要です。
Element要素
Element要素に関しては、BEM設計のElement要素と考え方は同じです。
Element要素単体では使用できず、BEM設計だとBlock要素、FLOCSS設計だとLayout要素、Component要素、Project要素のいずれかの要素に依存した要素になります。
- Element要素のクラス名の命名規則ルール
- Block名(Layout名、Component名、Project名) + '_' + Element名
アンスコ(_)でBlock名とElement名を接続します。
FLOCSS設計では、通常アンスコ(_)2つだったと思いますが、1つでも良いのでは?(短くなるし・・・)ということで、1つにしています。
- Layout要素
-
<header class="header">
<div class="header_inner">
<a class="header_logo">
<img src="/img/logo.png" alt="">
</a>
<button class="header_menu"></button>
</div>
</header>
- Component要素
-
<ul class="list">
<li class="list_item">リストアイテムテキスト</li>
<li class="list_item">リストアイテムテキスト</li>
<li class="list_item">リストアイテムテキスト</li>
</ul>
- Project要素
-
<section class="sec">
<h2 class="heading">見出し</h2>
<p class="sec_lead">リード文</p>
<figure class="figure">
<span class="figure_cover">
<img src="xxx.jpg" alt="">
</span>
</figure>
</section>
いくつか例をあげてみました。
今回は、Layout要素、Component要素、Project要素そしてElement要素の解説とクラス名の命名規則についてでした。
ポイントをまとめると、
・Layout要素とProject要素の区別
・Component要素とElement要素の区別
これらをクラス名ではなく、要素で判断できることが重要です。
次回は、Modifierについても触れて、もう少しクラス名の命名規則について解説します。