Takazudolog

Takazudo's blog on GitHub

RSS Takazudo

OOCSSとSass

| Comments

  • [ CSS ]
  • [ Sass ]
  • [ OOCSS ]

CSS Preprocessor Advent Calendar 2012の10日目、@Takazudoです。

僕はSassが好きです。なぜならSassにはextendがあるからです。その理由を、社内勉強会で発表した、以下のスライドで話したことを補足しつつ、書きます。

OOCSSってなんぞ

まず、Sassのextendが素敵な点を紹介する前に、OOCSSについて簡単に紹介します。

OOCSSというのは、Nicole Sullivanという人が言い出した考え方です。そのプレゼン資料やビデオなどは、本人が発表したものが、slideshare等にアップされています。

OOCSSのサイトの例えばこのページを見ると、divのclass属性にsize1of3だとsize2of3だとかいうのが使われているのがわかります。さっとだけOOCSSのことを見た人の中には、「あーOOCSSって、そういう便利系クラスをいっぱい付けてやるスタイルのことなのね。知ってるわーそれ2年前からやってわー知ってたわー」という人が、なぜか多いのですが、OOCSSというのはそういうことじゃーないんです。

OOCSSとは、ページの部品を「モジュール」という単位で分けて考えることで、サイトのメンテナンス性とパフォーマンスを上げる考え方の一つです。そして、複雑な部品については、このモジュールについて、他のプログラミング言語における、クラス(HTMLのclass属性とは異なる、プログラムにおける雛形の意)の継承の考え方を利用し、効率的に拡張していく…というのが、OOCSSのキモとなる部分であると、僕は捉えています。その実現の方法として、class属性に複数のクラスを当てる手法をとる… ということになります。

それを、簡単なモジュールを作りつつ、見ていくことにします。

黒か白か

まず、TwitterとFacebookのボタンを作ってみます。
Twitterボタンは赤、Facebookボタンは青…としましょう。そんなコードを、おれならこう書くぜ!ドーーン

m9(^Д^)プギャー と言われてしまいそうですが、これは、よく非難されるような、典型的なダメなクラス名の付け方…あの時のオレはどうかしちまってたんだ… とも言えるようなクラス名です。これは、柔軟性はありますよね。うん… でもCSSって、一体何なんだろうね…

ちなみに、このサンプルでは、ただの赤青のボタンですが、これは、同じような見栄えを持つ、めちゃくちゃリッチなボタン… しかし、その2つの装飾は異なる…であると、応用をきかせて、想像してください。イマジネーションの側面が重要です。

そんなダメダメなコードをdisりまくる、セマンティック野郎の書いたコードがこれです。

オーセマンティックデスネー
ではそのCSSを見てみましょう。

ハハハ・・・セマンティック最高だよね・・・
同じCSSをコピペして使うなんてさ・・・
おいおい、でもセマンティックは重要だろ?
クラス名には意味をもたせるべきだろ?
いやいやしかしこのCSSは無いでしょ。
ほかにも似たようなgoogle plusボタンができたらまたあんた同じCSSコピペするつもりでしょ?
じゃあどうすればいいっていうのさ!

ということになってしまいますよね。
この2つのコードは、言ってみれば、黒か白かという両極端なコードです。柔軟性を追求すれば、前者はまぁそりゃ柔軟であることには違いないですが、それ、CSSの意味ってなんなんですか?ってなりますし、後者はHTMLとしては理想ですが、CSSの中は大変なことになってしまいます。

あーほんとHTMLとCSSってなんでこう面倒くさいんでしょうね。

…こえますか?…聞こえますか?…僕はいま、あなたの脳内に直接語りかけています!OOCSSを使うのです!YES!

OOCSSっぽい書き方

と、そんなコードを、OOCSSでは以下のように書きます。

OOCSSではーベースのモジュールに、スキンを適用する…というふうに書くのです。複数のクラス名を利用して。

ここでのベースのモジュールというのは、クラス、btnbaseが表現するもの。ここには、ボタンの共通スタイルが適用されています。その上で更に具体的なバリエーションは、twitterfacebookといったような、スキンとしてのクラスで適用するという形です。

これが、プログラミング言語における、「クラスの継承」っぽいでしょ?っていう感じでObjected Oriented CSSと名付けられたようです。まぁその呼び方はどうなのよっていう意見もありますが、要するにこういうのがOOCSSの考え方(の一部)です。これなら、CSSに無駄がありませんね。同じようなgoogle plusボタンが現れたとしても、btnbase googleplusっていうクラスをあててスタイルが適用されるように作ればいいんですから…!

オイオイその冗談みたいなクラス名は何だ

でもちょっとまってください。

「このクラス名のどこらへんがセマンティックっていうんだよ?え?btnbaseだって?ふざけてんのかね。そんなのはblackborderがちょっとマシになったようなもんじゃないんですか?」

とセマンティック野郎が言いそうです。そのストリクトで真っ直ぐな精神は買いましょう。しかし、クラスをよりセマンティックにすれば、CSSはどんどん複雑に…。どうすれば…!という問に対しては、OOCSSは、「そんへんはある程度妥協して諦めろ」と答えます。OOCSSの考え方を用いれば、このbtnbaseのようなクラス名を作り、それをHTMLのclass属性に書くことになります。これはセマンティックなクラス名とは言いがたい…しかし!これがパフォーマンスとメンテナンス性を考慮した、最適解である…というのが、OOCSSの考え方です。なので、ただ単に便利なクラス名をポコポコ作って組み合わせれば素敵でしょ?っていうわけじゃないのです。

それにしたってそんな変なクラスを付けるなんて、中途半端な感じがしませんか?そうかも知れません。しかし、「CSS is too fragile」。CSSはあまりにも壊れやすい。CSSの機能は、はっきり言ってショボイ。プログラミング言語であれば、複雑さに対処する方法は色々と用意されています。しかし、CSSにはそのようなものがないと言ってしまっていいでしょう。とてつもなく長いCSSファイル - 赤の他人が書いたものを、すらすらと解読することができるでしょうか? それは、やっている人なら分かると思いますが、なかなかにしんどい作業です。

なんどでも言いたいこと、「CSSはショボイ」。しかしそれゆえに、その壊れやすいCSSを、丁寧に考えて書く必要があるのです。「そんな変なクラス」と呼んだもの、それは、具体的すぎず、なおかつ抽象的過ぎない、ちょうどいい具合の、そのUIを表現するクラス名ということになるでしょうね。

枠 + モジュール

OOCSSは、このようなモジュール+スキンの考えに加え、枠組みを作って、その中にモジュールを突っ込んで使えるようにしろというような考え方もあります。このアンチパターンが、例えば以下の様なコードです。

.sidebar {
  ...
}
  .sidebar h1 {
    ...
  }
  .sidebar ul {
    ...
  }
  .sidebar .banners {
    ...
  }
  .sidebar .primarynav {
    ...
  }
  .sidebar .secondarynav {
    ...
  }

サイドバーというのは、色々なモジュールが入る可能性がある、「大きなもの」です。上のコードは、OOCSS的に言えば、そのサイドバーを「大きなモジュール」として捉えてしまっている書き方であると考えることができます。実際、上のコードでは...で済ませていますが、その中にはspanなりliなり別の要素がボンボン入り、ネストは深く深くなっていくはずです。そうなれば、サイドバーという大きなモジュールに対応するCSSは、どんどん長く、深くなっていってしまいます。

これは、「粒度が大きすぎる」状態です。もっと細かく、再利用可能な適切な単位のHTML+CSSの塊を「モジュール」として考えましょう。そうすれば、メンテナンス性もアップでしょ?この例だったら、例えば以下のように細かく、一つずつを小さな「モジュール」として捉えるのです。

.sidebar {
  ...
}
.sidebarHeading {
  ...
}
.sidebarList {
  ...
}
.sidebarBanners {
  ...
}
.sidebarPrimarynav {
  ...
}
.sidebarSecondarynav {
  ...
}

そうすれば、一つのモジュールが複雑になった時でも、見ればいいのはそのモジュールの部分だけですので、後からの変更も比較的容易です。ページを構成するUIを、適切な大きさの、小さなモジュールの集まりと考えることで、コードを整理するのです。

ついでに言うと、弊社ピクセルグリッドでは、コーディングする際、そのようなモジュール一覧を作ってから具体的なページを起こすようにしていますよ。例えばこんなふうに。そして、モジュールの一番外側の要素には、クラス名としてmod-モジュール名をつけているんです。そうすれば、クラス名が被るっていうこともかなり少なくなるでしょう?ついでにCodeGridというサービスで記事を書いていたりもするので気になる方はチェックしてみてね…!

…と話がそれました。
そんな風に、モジュールで考えるのがOOCSSの基本的な考え方なのです。そのために、ある程度セマンティックでないクラス名は致し方なし。だって「The world is not always perfect」だからです。ある程度の抽象さをもったクラス名を使うという感じですね。繰り返しになりますが、borderredとかいうクラス名を付けることがOOCSSじゃないんですよ。

ページを構成するUIを、モジュール単位で整理して考えることが重要なんです。

mixin + include

そんなこんなで、要素のclass属性を利用し、モジュールモジュールした組み方がOOCSSなのですが、Sassを使えば、そんなことをしなくても、セマンティック野郎の野望を実現します。それも、CSSの管理性も確保した上で…!そんな素敵なSassでこのボタンを書いた例がこれです。

HTMLにはtwitterbtnfacebookbtnという、コンテンツそのものを表現するようなクラス名を、そして、Sassファイルの中では、これらのクラスセレクタに対し、ベースとなる、今OOCSSで.btnbaseとして定義してたスタイル - これをmixinとして定義しておき、これをまるっとincludeします。

こうすれば、先ほど問題になっていた問題が解決されているのが分かるでしょうか? クラス名はセマンティックで、CSSの管理性も確保されているのです…!ドヤーーというのがSassの素晴らしいところです。

extend

ですが、実は、このようにOOCSS的なことをSassでやるのには、extendの方が優れています。extendを使うと、以下の様なコードになります。

.btnbaseに当てられたスタイル群をもってきますよーという感じです。

なぜextendのほうがいいかというのは、出力結果のCSSを見てみるとわかります。左が、先のmixinの例が出力したCSS、右が今回のextendの例が出力したCSSです。

mixinincludeした場合は、同じコードが2箇所に出力されてしまいます。それに対し、extendの場合は、同じスタイルらを、セレクタをまとめて出力してくれるのです。

HTML+CSSではできないことを平然とやってのけた…!痺れるし憧れますね。個人的には、これこそがSassのもたらす最大のメリットだなーと感じます。extendは、そんな風に素晴らしい構造性をCSSにもたらしてくれます。

このような書き方を、OOSassと呼ぶ人もいるようです。

placeholder selector

ついでに言っておくと、Sass3.2からは、placeholder selectorというものが追加されました。これを使うと、今出したextendの例が出力する.btnbaseというモジュールのベースとなる、抽象的なクラスを、出力させないようにすることができます。

これの出力結果が、以下の右。左は、先のように、普通に.btnbaseextendした場合の出力です。.btnbaseextendした時と比べると、%btnbaseextendした方には、赤文字で書かれたクラスセレクタが存在していないことがわかります。

我々は、Sassを利用することで、他のプログラミング言語に用意されている、「抽象クラス」のようなことを、実現できることとなります。おお、ブラボー・・・

Sassのextendが素敵まとめ

そんなSassのextendが素晴らしすぎるよねということを図にまとめると、以下のようになります。

OOCSSでは、CSSでベースとなるモジュールを作り、スキンを作り、そのスキン適用を、HTMLのclass属性上出やるしかありませんでした。しかし、Sassを使えば、それは全てSCSSファイルの中で完結します。モジュールにスキン適用…ここまでを全てSass任せにできるのです。

これで、はじめに出たセマンティックな人も柔軟性重視な人もニッコリというわけですね。いやーSassって素晴らしいなー。

でもやっぱOOCSSか?

なー、Sassって素晴らしいなー… 完全無欠だなー… と思ってたんですよ。以下の記事を読むまでは。

この記事が言っているのは、「OOCSS的なことをSassでやるのは確かに素晴らしいさ。でも、そんな風にextendしまくると、出力結果のCSSで、超大量のセレクタが並ぶことになり、結果的にCSSの容量がふえまくっちゃうことになるんだよ?」ということです。

これは、先程のextendの結果に並ぶ、

.btnbase, .twitterbtn, .facebookbtn {
  ...
}

の部分ことを言っています。この例ですと、具体的なボタンのスキンは2つだけだからまだ良いです。しかし、この「具体的なボタン」というものが、100個ぐらいあったらどうでしょう。100このクラスセレクタがここに並ぶことになるんですよ。さらに、この例だと単純だからいいものの、実際には中にspanだの別の要素が並ぶことになります。そうなると、もう大量のセレクタがCSSに書きだされてしまう…!ということになってしまうんですよね。

これは確かに盲点です。それだったらHTMLのclass属性でOOCSSした方がいいかもしれません。しかしそうするとHTMLにスタイル指定の一部を担わせることになり… と、悩みはつきません。

まとめ

HTMLもCSSも完璧なものではありません。その完璧じゃない部分を、Sass等のCSSプリプロセッサは、大いに補強してくれるものですが、それで万事OKだというわけではない事も念頭に入れておく必要があるでしょう。

複雑なextendが容量の大きいCSSを作ってしまう… これは確かに問題ではありますが、かなりモジュールの数が増え、複雑になりすぎてしまった時にしか問題にならなそうではあります。

結局のところ、CSSプリプロセッサを使ったところで、「CSS is too fragile」の根本的な問題が解決されたわけではありません。その部分を解決するのは、やはりモジュール感を意識した無駄のない設計と言えるのではないでしょうか。

あなたはどのようにCSSを書いていますか? この記事を読むことで、少しでもCSSの設計に対する思慮が深まっていただけたら幸いです。

CSS Preprocessor Advent Calendar 2012、次はコバさんです。

お読みいただき、ありがとうございました。

Comments