第2回「コンポーネント」

001.png

100年後も崩れないCSS勉強会、第2回です!というわけで、きょうはコンポーネントについてお話しさせてください。

002.png

突然ですが、こちらはなんのへんてつもない Amazon のページです(2015年9月29日現在)。このページをよく見てみると、同じような見た目のものがあると思いませんか?

003.png

例えば、ヘッダーのメニューのなかの、右に小さな矢印がついたリンクとか…

004.png

例えば、サイドバーのカテゴリーの見出しと各項目が一覧になっているリンクとか…

005.png

本の書影とカテゴリーの見出し・本のタイトルが一緒になったリンクもあります。

006.png

さらには、ページのなかでオレンジ色の太字の見出しなんかも、文字の大きさは違うけど同じ見た目ですね。

007.png

こんなふうに、ウェブページはたくさんの要素があるように見えて、案外おなじ見た目の要素を繰り返したり、組み合わせることで作られています。

008.png

このような共通した要素のことを、ここではコンポーネントと呼びたいと思います。

009.png

「共通している」ということを言い換えると、「ここだけではなく他の場所でも再利用できる」ということでもあります。

010.png

それでは、さきほどの Amazon のオレンジ色の見出しの部分をコーディングするぞ!となったら、どんなふうに書くでしょうか。

011.png

例えばこんなふうにそれぞれ class 属性に名前をつけて、スタイルを指定したとします。でも、この3つをよく見ると、文字の色や太さの指定はどれも共通していて、違うのは文字の大きさだけですね。

012.png

じゃあ、ということで共通しているスタイルは .title という class セレクタのスタイルとして指定しておいて、それぞれの文字の大きさだけ class セレクタを追加して指定するようにしたら、どうでしょうか。こう書くと、文字の色や太さを変えたくなったときも、1行変えるだけで一気に変更できるので楽なのではないでしょうか。

013.png

この楽をしたいという怠惰な考えをもっと進めると、.page だとか .section だとかっていうのは「場所の意味」を指しているわけですが、どうせこのスタイルでは文字の大きさしか指定していないので、large だとか medium といった「見た目の意味」で指定できるようにするのは、どうでしょうか。こう書くと、ページの下のほうで 16px の見出しをつけたい!って思ったとき、その要素がどんな意味を持つ場所にあったとしても、HTML で .medium と class を追加するだけでスタイルを指定できて便利じゃないですか?

014.png

しかし、この名前のつけかたには問題があります。というのも、CSS はスタイルを適用する範囲を指定できないからです。ここでは .large という名前をつけていますが、他の場所でも大きい要素を表現したい場合に .large という名前をつけることも当然あると思います。もちろんあとから書いた .large.title.large に影響するので、ぜんぜん想定していない見た目になってしまいます。.large とかいう競合しそうな名前をつけないように気をつければいいって話なんですけど、現実的に意図しない見た目になっちゃたよオイというのは CSS を書いていて「あるある」なできごとですよね。

015.png

じゃあどうすればいいのか? ひとつの解決策としては、CSS の仕様が足りないのであれば自分たちで工夫しようということで、.title-large といった名前にするといいんじゃないかという考え方があります。こう書いておけば、おもむろに誰かが .large って書いても影響を受けないので安心だし、いままで .large だけだと何についてのスタイルなのかわからなかったものが、.title の見た目を指定しているスタイルシートであるということと、.title の文字の大きさを指定しているスタイルシートであることが、名前から伝わってくるように思います。

016.png

CSS 設計業界(?)では、このような考え方を説明するときに BEM(ベム)(ロシア発祥)という概念を利用することがあります。BEM では、ここでいう title のことを「Block」と呼んでいて、

017.png

large とか medium といったバリエーション違いを表している名前を「Modifier」と呼んでいます。

018.png

こちらはなんのへんてつもない検索フォームです。form 要素の .search-form のなかに、テキストフィールドの .search-form-textfield と、検索ボタンの .search-form-button という要素が入っています。

019.png

BEM(ベム)(ロシア発祥)では、ここでいう search-form を「Block」と呼んでいて、

020.png

こんなふうに search-form の中に入っている textfieldbutton といった要素を「Element」と呼んでいます。BEM(ベム)(ロシア発祥)は、「Block」「Element」「Modifier」の頭文字を略した名前なんですね。

021.png

でも、こんなふうに3種類の概念がひとつの名前に混ざっていると、いったいこの名前は Block なのか Element なのか Modifier なのか、どれを指しているのかわからないですよね…?

022.png

そこで、BEM の概念を理解しやすいように、MindBEMding(マインドベムディング)という命名規則が考え出されました。Element の前にはアンダーバー2つ、Modifier の前にはハイフン2つをつけることにしようじゃないか。これで Element と Modifier の区別がつく!やったー!

023.png

さきほどの検索フォームを MindBEMding の命名規則を用いて書いてみたら、このようになるでしょうか。結果的にまぁ名前がめっちゃ長くなっちゃうわけですが、でも、textfiledbuttonsearch-form のためにある要素だって、わかりやすくなったのではないでしょうか。

024.png

巨大な検索フォームを作る必要があっても大丈夫。large という Modifier がついたときのスタイルを指定すればいいんです。意味と見た目を分離して、どこでも再利用できる部品として定義する。同じ記述はできるだけ共通化して、全体を把握しやすくする。仕事も速くなって、リニューアルもかんたんです。コンポーネント、最高!

025.png

こんなふうな命名規則や考え方、またディレクトリ構成やファイルの分け方などはいろいろと提唱されていますが、どれもコンポーネントを意識して、いちど書いたスタイルの再利用性を高める、という視点は同じです。MindBEMding のハイフン2つやアンダーバー2つといった命名規則だって別に強制されているわけではなく、壊れにくい CSS を書くためのヒントとして、どう書いたっていいし、なによりチームメンバーや半年後のすべてを忘れた自分に伝わればいいんじゃないかなと思います。

026.png

さて、こちらはなんのへんてつもないタブのメニューです。クリックするとページに移動して、選択したタブの色がオレンジ色に変わるよくあるやつ。このスタイルがページのなかで何度も登場するので、業を煮やしてきょうはこれをコンポーネントにしようと思います。いったいどうやって書いたらいいでしょうか?

027.png

1案としては、.global-menu を Block の名前として、そのなかにあるやつを .global-menu からはじまる名前にして .global-menu-item にする。そうすれば、.global-menu 関連の要素なんだなっていうのが伝わりますね。そして、選択中のタブには .active って class をつけることで区別する。

028.png

いや、当プロジェクトでは Modifier は先頭に .is- をつけております、とか。

029.png

いや、そもそも .global-menu っていうけど、グローバルメニュー以外でもこの見た目あるよねってことで、どこでも使えるように意味ではなく見た目をあらわす .tab-menu って名前にしちゃうとか。ハイフンの区切り文字と Element の区別がつかないから、MindBEMding を取り入れてみるとか。

030.png

いや、俺はアンダーバー派だよっていうか、アプリケーションの他のコードはアンダーバーならアンダーバーにしちゃってもいいし、Modifier はアンダーバー2個からはじめるルールにしちゃうぞっていうのも良いと思います。

031.png

いや、.tab-menu がコンポーネントなのかどうかっていうのはよくわからないから、もっとわかりやすくするために先頭に .c- をつけるよ、みたいな几帳面な人もいます。

032.png

というような名前のつけかた、すでに考案されている命名規則は、この「CSS 設計の教科書」というすばらしい緑色の本に詳しく書いてあるので、ぜひ読んでください!

033.png

新規開発ならともかく、いま担当してるリリース済みのサービスで運用しながらどうやって導入していけばいいの?っていうことについては、このペパボの GitHub Pages にある「CSS 設計の長い夢」っていうページで @otthi さんが書かれているので、ぜひ読んでください!

034.png

まとめです。ページのなかでもし3回も同じ見た目の要素が登場することがあったら、ぜひこれはコンポーネントになるかもしれないって思って書いてみるのはどうでしょうか。きっと、あとで楽になったり便利になったり、壊れなかったりしてカッコいいと思います。ただし、逆になんでもコンポーネント化するとわけがわからなくなってしまうので、3回っていうのは結構よい基準なんじゃないかなっていうのは、やっぱりこの緑の本に書いてありましたので、僕も同意です!

035.png

とはいえ、コンポーネントって自分で思ってるだけでは他の人はなんのことかよくわからないですよね。だから、チームメンバーや半年後の自分が把握できるように、スタイルシートの説明書を作るのはどうでしょうか。そんなドキュメントの作り方を、次回はお話ししたいです。よろしくお願いします!