前回の、「CSSにルールを設けてさらに保守性を高めよう」では、CSS設計における基本的な考え方と、簡単に命名規則の話をしていきました。
CSSにルールを設けてさらに保守性を高めよう | ZeroPlus Media
次は、具体的な書き方の話をしていこうと思います。
目次
BEMの具体的な書き方
初めてBEMでの命名をしてみると、本当にこの書き方で合っているのか不安になると思います。
なので今回は、具体的な書き方を紹介していこうと思います。
基本的な書き方
まずは基本的な書き方です。
【BEMで書かない場合のコード】
<header class="header">
<h1 class="header-logo">
ZeroPlus <span class="header-logo-primary">Ad</span>Sense
</h1>
</header>
【BEMに直したもの】
<header class="header">
<h1 class="header_logo">
ZeroPlus <span class="header_logo__primary">Ad</span>Sense
</h1>
</header>
BEMの基本的な書き方として「Block_Element__Modifire」という書き方があります。
例えば、ここでは主に
header
というBlock_logo
というElement__primary
というModifier
という構成で作られています。
BlockとElementは例えるなら、住所がわかりやすいと思います。
「東京都豊島区」という住所があるとして、これは「Block_Element」の構造となっています。
「東京都の中にある豊島区」というような構造となっているように、「特定Blockの中にあるElement」という命名の付け方をしていきます。そうすることで、住所と同じように被ることなくclass名を命名することができるわけですね。
なので、上記のコードではheader
の中にあるロゴということでheader_logo
というclass名がついています。
Modifierは独特の考え方で、基本的な作りは同じですが、色や機能などで変化をつけたい場合に使います。
上記のコードのheader_logo__primary
というclass名は「その箇所だけ色に変化をつけたい」という使い方をしています。
Blockの中でBlockを作る
BEMを学びながら書いていると、構造上Elementにするのにも限界を感じるときがあります。
なのでBEMでは「Blockの中でBlockを作る」ということを行っていきます。
次のコードでは、header
というBlockのなかにheader-nav
というBlockを作って命名しています。
<header class="header">
<h1 class="header_logo">
ZeroPlus <span class="header_logo__primary">Ad</span>Sense
</h1>
<nav class="header-nav">
<ul class="header-nav_list">
<li class="header-nav_item">
<a class="header-nav_link" href="index.html#news">お知らせ</a>
</li>
<li class="header-nav_item">
<a class="header-nav_link" href="index.html#service">サービス</a>
</li>
<li class="header-nav_item">
<a class="header-nav_link" href="index.html#contact">お問い合わせ</a>
</li>
</ul>
</nav>
</header>
このようにして命名することで、「Block_Element_Element」のような書き方せずに、被りづらい命名をすることができます。
Mixを使う
BEMには「Mix」と呼ばれるテクニックがあります。Mixとは、一つの要素に複数のclassをつけることを指します。
Mixを行う目的として、「classごとに責任を分ける」というものがあります。
例えば、part1で紹介した次のコードを見てみると、.pagination_numbers
と.pagination_numbers__current
というclassが同じ要素に同居しています。
<div class="pagination">
<span class="pagination_numbers pagination_numbers__current">1</span>
<a href="" class="pagination_numbers">2</a>
<span class="pagination_between">…</span>
<a href="" class="pagination_numbers">10</a>
<a href="" class="pagination_numbers pagination_numbers__next"></a>
</div>
.pagination_numbers {
font-size: 18px;
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #d3d3d3;
background: #ffffff;
}
.pagination_numbers__current {
color: #ffffff;
border-color: #cb7aa6;
background: #cb7aa6;
}
このように書くことで、.pagination_numbers
が全体で共通のスタイルの責任を持ち、.pagination_numbers__current
が部分的なスタイルの責任を持つことになります。
責任を分担することで、再利用しやすく、保守しやすく、拡張しやすいCSSとなっているわけです。
接頭辞の具体例と注意点
part1の記事では、次のように概要を説明しましたが、今回はより具体的に解説していこうと思います。
BEMで書いたclass名の前につける文字のことを指しています。
役割として、そのclass名がなんの役割を果たしているかを示したり、class名の重複を避ける目的があります。
教材では次の接頭辞と役割が対応しています。
接頭辞 役割 l_class-name 汎用的に使えるレイアウトにつかう。sectionレイアウトなど。
headerやfooterは便宜上一つのレイアウトとして扱う。m_class-name 汎用的に使えるモジュール(コンポーネントと似たモノ)につかう。 u_class-name ユーティリティクラス(単一のスタイル・役割を持つclass)につかう。 js_class-name jsセレクタにつかう。
layout
layoutは共通化が行える「枠」専用のグループです。
このグループは原則として、width
やmargin
やpadding
などのようなレイアウトに関わるスタイリングしか行いません。
例を挙げるなら、コンテンツごとの上下のpadding
や、コンテンツ幅のwidth, marginに対して当てます。
/* コンテンツごとの上下の余白の例 */
.l_contents-wrapper {
padding: 120px 0;
}
/* コンテンツ幅の例 */
.l_container {
margin-left: auto;
margin-right: auto;
max-width: 1200px;
width: 92%;
}
ただし、「ヘッダーの背景色は黒」など「枠」と「あしらい」が結びついている場合は、必要に応じてレイアウト以外のスタイリングを行うことも問題ありません。
なので、教材ではわかりやすくするために、headerやfooterは全てlayoutとして扱います。
module
moduleとは、どこでも使いまわせるパーツのグループです。
このグループは基本的に、レイアウトに関わるスタイリングは行いません。
<div class="single_main_meta">
<div class="m_meta">
<time class="m_meta_date">2021.06.05</time>
<a href="category.html" class="m_meta_cat">SEO</a>
</div>
<!-- /.m_meta -->
</div>
/* モジュールの例 */
.m_meta {
display: flex;
justify-content: space-between;
align-items: center;
}
.m_meta_date {
color: #aaa;
font-size: 12px;
font-weight: bold;
}
.m_meta_cat {
color: #008db7;
font-size: 12px;
font-weight: bold;
width: 116px;
height: 25px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #008db7;
border-radius: 5px;
}
/* レイアウトを分担させている例 */
.single_main_meta {
margin-top: 16px;
}
教材ではわかりやすくするために、widthなどのレイアウトを指定しているモジュールもあります。
拡張性を考えると、レイアウトに関することはMixを使ったり、親要素に依存すると良いです。
utility
utilityとは、基本的にclass名がそのまま、CSSのプロパティ名と値を表現しているもののグループです。名前の付け方はEmmetを参考にすることが多いです。
また、このグループは、Web制作では補助的に使われることがあります。
/* 「.u_プロパティ-値」の順で指定している */
.u_mt-10 {
margin-top: 10px;
}
教材でも補助的に使っており、別箇所で使う際にも使えるような書き方になっています。
ユーティリティクラスは、同じスタイルを高頻度で使い回すWebサイトのデザインや、Web開発で主に使われます。
その他CSS設計を意識した書き方
ここまで扱った命名規則はCSS設計の代表的な方法の一つであり、他にもよいCSSを書くために気をつけることがあります。
詳細度をあげないこと
良いCSSを書くためには、セレクタの詳細度をコントロールする必要があります。
例えば、次のようなスタイルの指定をみだりに行うと、破綻が起きたり改修段階で不要なコストがかかります。
/* 同じ「!important」でしか上書きができなくなる */
.example {
color: red !important;
}
/* 上書きしづらい + 使いまわせない */
#about {
/* #aboutに対して与えるスタイル */
color: red;
}
基本的にはclassセレクタで同じ詳細度で書いてあげることを意識しましょう。
もちろん、「スタイルの上書き」を意図して詳細度をあげる場合は、問題ありません。みだりに詳細度をあげる書き方がよろしくないということです。
擬似クラスを使う場合や、プラグインで付与されるスタイルを打ち消す時などですね。
回避方法
どうしてもidセレクタを使わなければならない時は、次のような書き方で、詳細度をあげることを回避できます。
[id='about'] {
/* #aboutに対して与えるスタイル */
color: red;
}
デザイン依存の命名を避ける
命名方法で、次のように「見た目からつける」というのは避けた方が良いです。
:root {
--yellow-color: yellow;
--blue-color: blue;
}
.class-name__color-red {
color: red;
}
このように書いてしまうと、値が変わった時に名前まで変更しなければなりません。名前を変更しなければ予測しづらいコードになりますし、名前も変更が必要となると、保守性に欠けます。
なので、次のように「意味や役割からつける」方法がおすすめです。
/* 変数の命名も役割からつける */
:root {
--primary-color: yellow;
--accent-color: blue;
}
/* 警告用の色として扱う */
.class-name__warning {
color: red;
}
教材では、色変数でblack, white, grayがありますが、無彩色(白・黒・グレー)かそれに近い色は色自体が役割となっているので、例外としてそのままつけています。
CSS設計を学んでいく
ここまで細かく解説してきましたが、ここに書いてあることがCSS設計の全てではないです。
規模やサイトの種類によって、適切なCSS設計は変わりますし、現場によっては複数の手法は変わってきます。本記事ではCSS設計の考え方を学んでいただいて、他の記事や意見を見ながらCSS設計の根本の考え方とテクニックを身につけていってください。
また、初めから完璧を目指さず、書いていく中でブラッシュアップする方式で学んでいってもらえれば良いと思います。
最後に、より理解を深めてもらいたいので、参考になる記事を紹介させていただきます。
CSS設計を作っていく上での考え方の参考
別角度からのCSS設計の基礎
【初心者向け】模写修行流CSS設計を紹介! | 模写修行メディア
僕がCSSを書く際に必ず意識している CSSのコーディングルール30条|TAK / Web Creator.|note
CSS設計手法
BEMの基礎(図解付き)
【CSS設計】ゼロからわかるBEM超入門FLOCSS(公式)
GitHub - hiloki/flocss: CSS organization methodology.
他にも、OOCSSやSMACSSなど、いろいろありますが、基本的に目指しているのは「良いCSSを書くこと」なので、似た内容だったり、それぞれ合体させた手法だったりします。
勉強してみるととても奥が深く、合理的なのでぜひいろいろ調べてみてください。