OOCSS、SMACSS、FLOCCS、BEMなどいろいろなCSS設計思想が紹介されていますが、どれもメリット、デメリットがあって、どうにもしっくり来ませんでしたが、RSCSSというのを見つけまして、けっこういい感じだと思いました。
BEMの問題点
BEMではネストが3つ以上発生する場合に、設計思想が破綻していました。下記のようにコーディングしてしまいがちですが、BEMではElementのネストは推奨されません。ネストされる要素をSub-Elementとして定義するか、別のBlockとして定義する必要があります。
<!-- NG -->
<div class="index-a">
<ul>
<li class="index-a__item">
<dl>
<dt class="index-a__item__thumbnail">
<dd class="index-a__item__title">
<dd class="index-a__item__category index-a__item__category-press">
<dd class="index-a__item__description">
<dd class="index-a__item__readmore">
<a href="index-a__item__readmore__button">
<!-- OK -->
<div class="index-a">
<ul>
<li class="index-a__item">
<dl class="card-a">
<dt class="card-a__thumbnail">
<dd class="card-a__title">
<dd class="card-a__category card-a__category-press">
<dd class="card-a__description">
<dd class="card-a__readmore">
<a href="button-a">
Yahoo!の現場ではElementの階層を固定することで回避しているとのことです。今回の例であげれば下記のような感じでしょうか。
<!-- OK -->
<div class="index-a">
<ul>
<li class="index-a__item">
<dl>
<dt class="index-a__thumbnail">
<dd class="index-a__title">
<dd class="index-a__category index-a__category-press">
<dd class="index-a__description">
<dd class="index-a__readmore">
<a class="button">
ただ、BEMの考え方は、HTMLのコード量が肥大になりますし、これをテンプレートや汎用クラスにも全て適用していくのかというと、葛藤があります。どこまで許容し、どこまで厳格にするのかが、BEMを導入するにあたって難しいところです。コードの再利用性をよくするために導入しているはずが、BEMを導入するためにかえってコードを書き直しているなんてことにもなりかねません。また、サイト開発当初は設計できたとしても、運用中に設計できず破綻してしまっては、本末転倒です。
<!-- まだわかりますが -->
<ul class="list-a">
<li class="list-a__item">ああ</li>
<li class="list-a__item">いい</li>
<li class="list-a__item">うう</li>
<!-- ここまで来るとそろそろ拒否反応が… -->
<table class="table-a">
<tr>
<th class="table-a__cell-heading">ああ</th>
<td class="table-a__cell">ああ</td>
ただ、BEMの非常に優れているところは、一意のclass名を定義することによって、コードの再利用が可能なことと、classの重複による事故が発生しないところです。デザイン再現にあたり、container
、wrapper
、inner
といったclassを使用することがありますが、これをそのまま使うとclass名が重複する事故がおこることがあります。下記ではinner
とtitle
がCSSの重複を起こします。BEM的発想でclass名を引き継げば解消されますが、どこまで引き継ぐのか、BEMと同じ葛藤が出てきます。
<!-- よくある設計ミス -->
<section class="section-a">
<div class="inner">
<h2 class="title">WORKS</h2>
<div class="work-list">
<div class="inner">
<ul>
<li class="item">
<dl>
<dt class="title">
<!-- class名を引き継げば解消される -->
<section class="section-a">
<div class="section-a-inner">
<h2 class="section-a-title">WORKS</h2>
<div class="work-list">
<ul class="work-list-inner">
<li class="work-list-item">
<dl>
<dt class="work-list-title">
RSCSSでは
RSCSSでは子セレクタ(>)を使用することで、BEMの冗長で気持ち悪いところが解消されています。また_始まりのhelperクラスを使用することができます。フレームワークではなく、アイデア集とのことで、現場の裁量に委ねられている点も採り入れやすそうです。ただ、OOCSS的観点だと要素に依存しない(divを使用)したほうが拡張しやすいという発想なので、少しやりづらい部分もあるかもしれません。
タグセレクタがあると使用は厳しい
<div class="article-list">
<ul>
<li class="item">
<dl>
<dt class="thumbnail">
<dd class="title">
<dd class="category -press">
<dd class="description">
<dd class="readmore">
<a href="button">
.article-list{
> ul{
> .item{
> dl{
> .thumbnail{ }
> .title{ }
> .category{ }
> .description{ }
> .readmore{
> .button{
}
}
}
}
}
}
BEM的発想でコンポーネントをネストする
<ul class="article-list">
<li class="item">
<dl class="article-card">
<dt class="thumbnail">
<dd class="title">
<dd class="category -press">
<dd class="description">
<dd class="readmore">
<a href="button">
.article-list{
> .item{ }
}
.article-card{
> .thumbnail{ }
> .title{ }
> .category{
&.-press{ }
&.-ir{ }
&.-product{ }
}
> .description{ }
> .readmore{
> .button{ }
}
}
よく使うclass名もバッティングしない
<section class="section-a">
<div class="inner">
<h2 class="title">WORKS</h2>
<div class="work-list">
<ul class="inner">
<li class="item">
<dl>
<dt class="title">
.section-a{
> .inner{
> .title{ }
}
}
.work-list{
> .inner{
> .item{ }
}
}
最後に
最終的にはそれぞれの良いところを採り入れたものを導入すれば良いと思いますが、それぞれの設計思想と良いところ、悪いところを学ぶことはとても勉強になりますので、覚え書きしておきます。調べはじめてあまり時間が経っていないので間違っていることやわかりづらいところがあるかと思いますが、ご容赦ください。