これからSassを始めたい人へ!導入手順をまとめてみた(Dreamweaver対応)
- 576
- 439
WEB
こんにちは、店長です。
今回はSMACSSというCSSの設計方法から学んだ、CSSプリプロセッサとの良い関係についてまとめていきます。「SMACSSはなんとなく知ってるけど、どうしたらよいかわからない」「CSSプリプロセッサは使っているけど、うまく使えない」という方の参考になればと幸いです。
なお、CSSプリプロセッサとはCSSを拡張していろんな機能を追加したものを言います。もしCSSプリプロセッサを使ったことがないという方は、こちらの記事を参考にしていただければと思います。
これからSassを始めたい人へ!導入手順をまとめてみた(Dreamweaver対応)
もっとSassろう!慣れてきたら使いたいワンランク上のコーディング方法4選
※本記事では、2015年11月18日にいいオフィスで行われた「書籍『最強のCSS設計』出版記念イベント&勉強会―CSS設計、チーム開発を成功させるために必要なこと」で登壇したときの内容にさらに情報を加えてご紹介していきます。イベントのスライドは下記をご覧ください。
SMACSSとはCSS設計手法の一つです。『Scalable and Modular Architecture for CSS』の頭文字をとってSMACSSと呼ばれています。SMACSSの特徴は5つのカテゴリに分類をして、それぞれの考え方に合わせた設計を行うのが特徴です。
今回の記事では、SMACSSについての解説は割愛させていただきます。SMACSSの詳しい内容については、『Scalable and Modular Architecture for CSS』をぜひ読んでみてください。こちらは日本語に翻訳もされていて、かなり読みやすく参考になるところも多いのでオススメです。
またすぐに学びたいという方はCodeGridさんの記事が参考になるので読んでみてください。
SMACSSによるCSSの設計 – ベースとレイアウト | CodeGrid
もちろん『最強のCSS設計』でも紹介しています。気になる方はぜひ!
ここからはCSSプリプロセッサの機能に焦点をあてながら、どのような書き方をするのが良いのかまとめていきたいと思います。
今回はSMACSS × Sassでコードを記述していきます。
CSSプリプロセッサでもよく使う機能であろう入れ子。入れ子はクラスの親子関係が把握しやすく便利ですが、不必要に使い過ぎるとメンテナンスしにくいコードになる可能性があります。
例えば、このようなモジュールが存在したとします。
<div class="profile"> <div class="profile-image"> <img src="photo.jpg"> </div> <div class="profile-body"> <div class="profile-name"> ~ </div> <p> ~ </p> </div> </div>
このモジュールにスタイルを当ててみました。
.profile { width: 300px; .profile-image { > img { width: 100%; height: auto; } } .profile-body { background: white; font-size: 16px; .profile-name { font-size: 24px; } } }
入れ子を使って要素の親子関係も把握できるし、なんとなくいい感じですね。
こちらをコンパイルしてみましょう。
.profile { width: 300px; } .profile .profile-image > img { //深度が深い width: 100%; height: auto; } .profile .profile-body { background: white; font-size: 16px; .profile .profile-body .profile-name { //深度が深い font-size: 24px; }
コンパイルされたコードはこんな感じになりました。しかしよく見てみると、出力されたコードの中にはセレクタが多く、くっついてる部分が見受けられます。
とっても便利な入れ子ですが、入れ子をしすぎると以下のような欠点があります。
SMACSSではモジュール内のパーツは、それぞれ用途に合わせたのクラスを振ります。そしてモジュール内のタグに対してスタイルを当てる場合は、中のタグは変わることがないことを前提で当てます。
なので先ほどのスタイルはこんな風に書くとよりスッキリします。
.profile { width: 300px; } .profile-image { > img { width: 100%; height: auto; } } .profile-body { background: white; font-size: 16px; } .profile-name { font-size: 24px; }
親のクラスに対して入れ子するのではなく、モジュールのパーツごとに切り分けました。そしてそれに紐づくものみ入れ子にしています。
これをコンパイルするとこんな感じです。
.profile { width: 300px; } .profile-image > img { width: 100%; height: auto; } .profile-body { background: white; font-size: 16px; } .profile-name { font-size: 24px; }
ほぼコンパイル前と変わっていませんが、入れ子をした時よりも深度は浅くなり、把握しやすく、扱いやすくなりました。入れ子をしなくても命名規則でどのモジュールに属しているかは判断ができるので無理に入れ子にする必要はないのです。
厳密にルール化をしているわけではありませんが、自分がSMACSSで書く場合は以下の場合で入れ子をすることがほとんどです。
深度が深くなればなるほど、拡張性、保守性が低くなるのでなるべく深度を浅くするように心がけています。
@extend、mixinは頻繁に出てくるパターンを当てる際にとても便利です。ですが使い方を間違えると理解しにくく、単調なコードになりやすいので注意が必要です。
@extendは以下のように利用されます。
%shadow { box-shadow: 0px 2px 2px rbga(0, 0, 0, .2); } .profile{ @extend %shadow; } .media{ @extend %shadow; }
これはshadowのスタイルを.profileと.mediaという2つのモジュールに対して使用している例です。
まだこれならわかりやすいかもしれませんが、@extendを使用している箇所が増えるとコンパイル後にこのような形になります。
.profile, .hero, .header, .box, .side-nav, .nav, .tag, .media, .author, .member, .banner { box-shadow: 0px 2px 2px rbga(0, 0, 0, .2); }
@extendを使用するとこのようにたくさんセレクターが並び、見通しが悪くなります。また、CSSが出力される位置が、@extend元ということもあり、どこで@extendをしているのかわかりづらいという欠点もあります。
その点、mixinは@importした場所にスタイルが記述されるので@extendよりも見通しはよく感じます。ただ、大量のスタイルをmixinでまとめて使い回すのは、単調なCSSを大量に書くことにつながります。
以下がその例です。
@mixin circle { border: 1px solid #900; border-radius: 3px; background: #fff; } .profile { width: 300px; @include custom-border; } .media { padding: 20px; @include custom-border; } .article { background: #f7f7f7; @include custom-border; }
上記のようにmixinを使ってみました。このときのコンパイルされたCSSに注目しましょう。
.profile { width: 300px; border: 1px solid #900; //同じコード border-radius: 3px; //同じコード background: #fff; //同じコード } .media { padding: 20px; border: 1px solid #900; //同じコード border-radius: 3px; //同じコード background: #fff; //同じコード } .article { background: #f7f7f7; border: 1px solid #900; //同じコード border-radius: 3px; //同じコード background: #fff; //同じコード }
このように同じコードが含まれたコードが大量に出力されてしまいます。決して悪いとは言い切れないのですが、設計で解決できるのであればその方法を検討するとよいでしょう。
たとえば先ほどのようなコードの場合は、テーマとしてスタイルを別に切り出してもよいかもしれません。
.theme-border{ border: 1px solid #900; //同じコード border-radius: 3px; //同じコード background: #fff; //同じコード } .profile { width: 300px; } .media { padding: 20px; } .article { background: #f7f7f7; }
使うときはこのようにします。
<div class="profile theme-border"> <div class="profile-image"> ~ </div> <div class="profile-body"> ~ </div> </div>
このようにクラスを複数つけることで解決ができます。またHTML上でスタイルの付与が完結する形になります。
私の場合はまず@extendは使いません。理由は前述の通りで見通しがとても悪いと感じることが多かったからです。
またmixinは便利な機能でよく私も利用しています。ただ先ほどの例のように設計で解決できないかを考えた上でmixinを作ります。また複数人で運用するプロジェクトではどのようなmixinがあるかをコメントとしてちゃんと残すようにしています。
@importはCSSファイルを分割して管理できるためとても便利です。ただなんとなく分割をするのではなく、CSS設計に合わせた分割を心がけましょう。
style.scssというメインファイルに、他のファイルをすべて@importして一つのファイルとしてコンパイルする方法を提唱しています。
style.scssの中身は以下のようになります。
@import 'setting'; @import 'mixin'; @import 'base'; @import 'layout/grid'; @import 'layout/alternate'; @import 'module/btn'; @import 'module/profile'; @import 'module/nav';
他のファイルは、ファイル名の先頭にアンダースコアをつけます。こうすることで、アンダースコアをつけたファイル単体でコンパイルされなくなります。
_setting.scss、_mixin.scssはファイル全体で使うファイルです。_setting.scssは主に変数、_mixin.scssにはmixinをまとめます。先頭で呼び出すことで、それ以下のファイルでも変数、mixinを使用できるようになります。
またSMACSSの場合はlayout、moduleというディレクトリを作成して、カテゴリごとにファイルを作ります。このときモジュールは1モジュール、1ファイルで作成します。
モジュールはさまざまな場所で使い回しができる前提で作られます。なので1つのファイルの中でスタイルが完結していることが望ましいです。
完結していない状態とは、たとえば以下のようなものを指します。
.card { float: left; padding: 15px; box-sizing: border-box; } .card-inner{ background: color }
.profile { width: 300px; } .profile-image { > img { width: 100%; height: auto; } } .profile-body { background: white; font-size: 16px; } .card-inner .profile{ border: 1px solid #ccc; } }
これはprofileモジュールの中でcardモジュールに依存した書き方をされています。このようなコードが増えていくとファイルを分けていてもモジュール同士の依存関係が生まれてしまい再利用しにくいモジュールになってしまいます。この場合はサブクラスにしたり、モジュールを分けたりすると良いでしょう。
このようなモジュールがある場合は、リファクタリングするように心がけることで、常にモジュール同士が依存しない保守性の高いコードを書くことができます。
SMACSSではレイアウトルールとしてクラスの先頭に「l-」を付けるルールがあります。このような接頭語の考え方を_setting.scssでも取り入れるようにしています。
以下がその例です。
//color $color-primary: #ff0000; $color-secondary: #ffff00; $color-link: #ffffff; //width $width-container: 1200px; $width-main: 820px; $width-sub: 360px; //font-size $font-size-xlarge: 28px; $font-size-large: 20px; $font-size-medium: 16px; $font-size-small: 14px; $font-size-xsmall: 12px;
このようにプロパティ名を接頭語としてつけておきます。このようにしておくとテキストエディタのサジェスト機能で探すのが楽になります。また新しく案件にアサインされた人でも、迷ったらとりあえずプロパティ名を打てばサジェストしてくれるので変数が把握しやすくなります。
いかがでしたでしょうか?
CSS設計は私も常に悩みながら設計をしています。そして設計しながらも途中で変更することはよく起こります。そこで気をつけてるのが、常にあとで変更しやすいコードを書いておくということ。
今回のお話が少しでも皆さんのCSS設計のお役に立てれば幸いです。そして今回の方法よりもより良い方法や、こうしたほうがもっと良いというご意見があればぜひ教えてください!
もっとよいコードが書きたいので、今後も頑張って突き詰めていきたいと思います! それでは。
いいね!して、LIGの最新記事を受け取ろう。