①レイアウトごと1つのBlockとする
1つ1つのカードアイテムをまとめているul要素をまるごと1つのBlockと定義し、中身は全てそのElementとして完全にレイアウトとカード本体を一体のコンポーネントとする考え方。2カラム、3カラムのバリエーションはModifierを追加すれば再現できるため、デザイン再現上は特にこれでも問題ない。
ただし、仮にカードの中身を1つだけ取り出して別のところで単体で使いたいといった要望が出た場合、そのまま再利用するのはElementのみの単体利用を禁止するBEMのルールに反するため、新たなBlockを再定義しなければならないリスクがある。また、親Block以下の全ての要素が並列のElementとして命令されることになるので、カード本体の構成要素が複雑だった場合は特に命令に困る場面が発生しやすいというデメリットもある。
<ul class="card-list card-list--col3">
<li class="card-list__item">
<a href="#" class="card-list__inner">
<div class="card-list__thumb"><img src="img/001.jpg" alt=""></div>
<p class="card-list__txt">この文章はダミーです。</p>
</a>
</li>
</ul>
<div class="pickup">
<div class="pickup__card">
<!-- 表示はできますがElementの単体利用となるのでルール違反です! -->
<div class="card-list__inner">
//省略
</div>
</div>
<div class="pickup__body">
<p>このカード情報に対する説明テキストが入ります。</p>
</div>
</div>
②レイアウトを汎用グリッドとする
レイアウトとカード本体を完全に切り離し、レイアウトのほうはレイアウト専用の汎用グリッドBlockにまかせてしまうという考え方。これはCSS設計の基礎であるOOCSSでも提唱されている「コンテナとコンテンツを分離する」という原則に基づいた基本的な設計手法である。
あらかじめ2カラム、3カラム、4カラムなど必要な分だけのレイアウト専用のBlockを用意しておくことで、必要な場面で自由に中身を入れ替えて構成するシステマティックな実装が可能となる。コンテンツの中身は問わないので、どんなにコンテンツの種類が増えてもレイアウトの定義が1回で済み、効率という面ではこの方法が最も優れていると言える。
ただし、この手法はデザイン段階からあらかじめ決まったグリッドの中にコンテンツを入れる前提で設計されていないとうまくいかない。コンテンツごとに細かい変化があったりコンテンツ内容によってSP側のレイアウトだけ見せ方を変えたりといったイレギュラーが多発するような場合はメリットをうまく活かすことができないし、汎用的な名前だけで様々なバリエーションを作るのもなかなか骨が折れる。
<ul class="grid grid--col3">
<li class="grid__item">
<a href="#" class="card">
<div class="card__thumb"><img src="img/001.jpg" alt=""></div>
<p class="card__txt">この文章はダミーです。</p>
</a>
</li>
</ul>
<div class="pickup">
<div class="pickup__card">
<!-- カード本体はBlockなので単体利用が可能です。 -->
<div class="card">
<div class="card__thumb"><img src="img/001.jpg" alt=""></div>
<p class="card__txt">この文章はダミーです。</p>
</div>
</div>
<div class="pickup__body">
<p>このカード情報に対する説明テキストが入ります。</p>
</div>
</div>
③レイアウトを汎用グリッドとする
②と同様にカードのレイアウトとカード本体を別Blockとして定義するが、レイアウトは汎用的なものではなく、カードの種類1つにつき、それをまとめるレイアウト用のBlockもセットで1つ用意するパターン。
例えばxxx-cardに対してはxxx-card-list、yyy-cardに対してはyyy-card-listといったセットを用意する。
特定のカードとそれをまとめるレイアウトをゆるく結びつけておくことで、カード本体は単体で他の場所でも再利用できるが、そのカードを一覧化して表示する際にはレイアウトも含めて全体で1つのコンテンツというまとまりを維持する、折衷的なやり方である。
見せたいコンテンツの内容ごとにカードのスタイルもレイアウトパターンも少しずつ違うといった、汎用的化しづらいデザイン設計となっている場合には、無理に汎用化せず、影響範囲を限定したそのコンテンツ固有のコンポーネントとしておいたほうが扱いやすいこともある。
表示項目の増減を想定する
サムネイル画像とテキストだけのシンプルなカード一覧の場合、サムネイルエリア以外のテキストが入る領域には周囲に余白がある。
現状はテキストのp要素1つしかないので、そこに余白を付けてしまえばデザイン再現は可能だが、後から見出しやタグなど別の要素が挿入されたパターンが出てくる可能性は十分あるので、サムネイル領域とその他コンテンツ領域はdivで分割しておいた方が無難だろう。カード型に限らず、Blockの中のメイン情報が挿入されるエリアについては、常に「xxx__body」というElement名を付けたほうが良い。
BEMは親ブロック名さえ被っていなければElementの名前は他のブロックと共通であっても何ら問題ないので、役割ごとにあらかじめ使用するElement名を固定しておくと、命名作業が非常に楽になる。
- __wrapper(Blockの外側を囲む必要がある場合)
- __inner(Blockの内側を囲む必要がある場合)
- __thumb(サムネイル画像エリア)
- __body(コンテンツ本文エリア)
- __title(見出しテキスト)
- __text(テキスト)
【NG例】
<ul class="card-list card-list--col3">
<li class="card-list__item">
<a href="#" class="card">
<div class="card__thumb"><img src="img/001.jpg" alt=""></div>
<p class="card__txt">この文章はダミーです。</p>
</a>
</li>
</ul>
【OK例】
<ul class="card-list card-list--col3">
<li class="card-list__item">
<a href="#" class="card">
<div class="card__thumb"><img src="img/001.jpg" alt=""></div>
<!-- カード本体のテキスト情報が入るbodyエリアを定義する枠を追加しておく -->
<div class="card__body">
<p class="card__txt">この文章はダミーです。</p>
</div>
</a>
</li>
</ul>
classの省略はしない
シンプルなグローバルナビのようなケースでは、ul>liで構造が固定されるということもあり、li要素やa要素のclassを省略したとしても実害はほぼないと思われるが、どのような使われ方をするのか、どのような変更が入るのか不確定なコンポーネントに関しては特にclassの省略はNGである。
①リンクなし一覧パターンで利用する場合、カード本体のBlockをa要素に当てていたが、a要素がなくなってしまったため、1つ上のli要素をcard-listのElementであり、かつcardのBlockでもあるMix要素として指定している。もともとcard-listはレイアウトのみ、cardはカード本体のスタイルのみでお互いに干渉しあうスタイルは持っていないので、このような指定が可能となる。
②コンテンツ量が増えsection要素に変更する場合でも、スタイルが要素ではなくclassに定義されていれば(階層構造さえ変わらなければ)CSSはそのままでマークアップ要素を変更することができる。
<ul class="card-list card-list--col3">
<li class="card-list__item card">
<div class="card__thumb"><img src="img/001.jpg" alt=""></div>
<div class="card__body">
<p class="card__txt">この文章はダミーです。</p>
</div>
</li>
</ul>
<div class="card-list card-list--col3">
<section class="card-list__item">
<a href="#" class="card">
<div class="card__thumb"><img src="img/001.jpg" alt=""></div>
<div class="card__body">
<h2 class="card__tit">見出しテキスト</h2>
<p class="card__txt">この文章はダミーです。</p>
<ul class="card__tag tag-list">
<li class="tag-list__item tag">タグA</li>
</ul>
<div class="card__btn">
<p class="btn-more">詳しくみる</p>
</div>
</div>
</a>
</section>
</div>