はじめに
はじめまして!
初めて投稿します、じいやと申します。
最近、WebアプリのUIリニューアルに際して今までのCSSを全て消して、新しいCSSを書くというタスクを担当しました。別のプロジェクトでBEMを一瞬使っていたので、今回もBEMを使ってやってみようと思って進めていきました。
その中で、問題、そして葛藤があったのでそれを書いていこうと思います。
背景
普段BEMを書くとするとCSSではなくSassと使用すると思うのですが、今回は背景もありCSSでやることになりました。
思えば、ここでSassを使わないならBEMを使う旨味が薄くなってしまうので冷静になってBEMではないものを考慮するべき、もしくはSassを使うように考えるべきだったのかもしれません。
BEMとは
BEMを知らない方のために軽く説明すると、BEMとは
- Block
- Element
-
Modifier
の頭文字をとったもので、CSSの設計手法です。
BEMではHTMlの要素を細かく分解して、コンポーネントごとにしていきます。
Blockは親コンポーネント、Elementは子コンポーネントを指します。
Modifierはその要素の特徴を装飾するトッピングのような物です。
これだけだと何を言っているかわからないですよね笑
例をあげて説明します。
例えば、フォームを作るとします。
HTMLはこんな感じに
<form>
<label>Email</label>
<input type="email" name="email"/>
<label>Name</label>
<input type="text" name="name"/>
<input type="submit" value="Submit" />
<input type="reset" value="Reset" />
</form>
ここにBEMを入れるとすると、まず大きなBlockとしてformがあります。
ですのでとりあえず適当に
.form {
max-width: 85%;
margin: 24px 0;
padding: 24px;
}
とします。
次に、formの中にあるものを見ると<label>
<input>
ですね。(厳密に言えば<input>
に入力欄とボタンがあります。)これらは、formというBlock内のElementになります。
BlockとElementはアンダースコア2つで繋ぎます。
ですので、下記みたいにします。
.form {
max-width: 85%;
margin: 24px 0;
padding: 24px;
}
.form__label {
display: block;
font-size: 1.2rem;
margin-bottom: 12px;
}
.form__input[type=text],
.form__input[type=email]{
display: block;
width: 100%;
height: 28px;
border-radius: 5px;
margin-bottom: 12px;
}
.form__button {
display: block;
background-color: #03fc90;
width: 80px;
height: 36px;
border-radius: 5px;
margin-bottom: 12px;
}
いい感じです。
最後に、Modifierです。これは、要素を修飾するものです。今回はリセットボタンをグレーにしましょう。(これに関してはいくつか書き方があると思いますが、CSSを使っていて.form_button
のcssを継承したいので下記のようにしました。)
~~
.form__button {
display: block;
background-color: #03fc90;
width: 80px;
height: 36px;
border-radius: 5px;
margin-bottom: 12px;
}
.form__button.--gray {
background-color: #d9d9d9;
}
クラスをそれぞれのタグにつけたのが以下です。
See the Pen yLyJGEd by RyojiK74 (@ryojik74) on CodePen.
とてもCSSが整っていて、わかりやすいですよね
CSSを見ただけでなんとなくどこに使われているかがわかります。
問題はここからだぁ!!
急にテンションが高くなりましたが、ここから複雑になってきたのです。
まず僕たちは、デザイナーから受け取ったデザインを見てみました。するとそこには、同じスタイルをもつコンポーネントが多くありました。まあとりあえずページを作ってみて、共通化できるところはしていこうということで進めていきました。
1ページ目(使い回し)
See the Pen yLyJGEd by RyojiK74 (@ryojik74) on CodePen.
次のページを見ると同じボタンが今度は<form>
内ではなく、リンクとして使われていました。
とりあえずさっきのクラスを使いまわそうとしました。
2ページ目
See the Pen another_page by RyojiK74 (@ryojik74) on CodePen.
見た目は悪くない...だけど、これHTMLをよく見るとわかると思いますが、contact
というブロックなのにform__button
が存在してしまっている...。うーん、ビミョい...。
でも、ボタンのスタイルを一括で変えたいというタイミングがこれ以降であるかもしれないことを考えると同じスタイルだが別の名前を持つ物を作るのは避けたい...。
泣く泣く、ボタンコンポーネントは例外として、.content-button
というクラスを作ってしまいました。
いや、これSassだったら@extend
つかってもっとスマートにbutton
継承しながらかけるのに...。
なんやかんや、.content-button
のおかげで一応作業を進められるようになった我々を待ち構えていたのはmargin-bottom
君でした。
レイアウトとコンポーネントの狭間
次のページでも、同じボタンが使われていましたが 一つ違いがありました。それは、彼だけ**margin-bottom: 36px;
**だったのです。
今まで、12pxだったから甘えてきたものの3倍の36pxはきついものがありました。
**というかそもそもコンポーネントで設計する場合はmarginなどのレイアウトに関わる部分はつけるべきではありません。**つけてしまうと、このように再利用性が著しく下がってしまいます。
正直詰みの状態でした。
BEMの見やすさやメンテナンス性を保持しようと考えると--mb-24
みたいな汎用クラスを作成はしたくないですし、かと言ってCSSのメンテナンス性を踏まえるとクラスを分けたりしたくはありません。最終的に僕らはプロジェクトのエンジニアリーダーに話しをして、タグに直接styleを埋め込むもしくはページのheadにstyleを埋め込み、そこで各ページに必要なmarginなどを書くことでとりあえず落ち着きました。
まとめると問題はなんだったのか??
Sassの@extend
がないCSSでメンテナンス性とBEMの両立をしようとしたのが無謀だったのだと思います。
使うフレームワークによるとは思いますが、BEMを使い、さらにコンポーネントを作ってそのメンテナンス性をあげる場合はSassを使わない手はないと思います。
もっと設計の段階でいろいろ見越して考えるべきだったと後悔しています。
僕とは違いみなさんは先のことをきちんと考えてから導入されているかもしれませんが、これからBEMを考えてみようと思う方に届けばいいなと思います。
ここまで読んでくださりありがとうございました