CSSのメタ言語Sass(SCSS)、LESSの完全入門

  • 252
    Like
  • 0
    Comment
More than 1 year has passed since last update.

はじめに

これまで、CSSは素でstyle.cssのようなファイルにスタイルを書く方法が主流でした(私も最近までこちらでした)。
ですが、CSSだけで書いていると、どうも拡張性や保守性に欠けたりしてしまいます。

仕事だとあるあるだと思いますが、同じようなスタイルをひたすらコピペで違うクラスやIDを使っていたり、どうしても一部だけ違うデザインを適用させたくなってcolor: red;!important;とか使って設計が崩壊していったりと、開発する上でCSSだけで書いているとルールを作るのも大変だし、チームで苦労することになります。

そこで、最近ではメタ言語と呼ばれる、CSSをよりプログラミングに近い形で書ける言語が出てきました。

これらのメタ言語とは、よりCSSを抽象的に書くことができて、プロセッサと呼ばれるものを使ってCSSを生成します。

つまり、もっと直感的にCSSを書けるってことですね!
かゆい所に手が届くというか、、そんな感じですw

CSSのメタ言語

有名なのは、

なんかがあります。

Sass(SCSS)

Sassが、括弧でSCSSと書いてあるのは、もともとSASS記法というので書かれていたんですが、Sass3.0からCSSちっくに書くことが出来るSCSS記法というのでも書けるようになったためです。
ようはどちらで書いても、同じCSSが生成されるので、自分に合った方を使えばいいと思います。

Sassの使い方

  • rubyのインストール

Sassはrubyでコンパイルするのでとりあえずrubyが必要です。
私の環境(centOS)でインストールしたやり方をすべて残しておきます。

$ wget https://cache.ruby-lang.org/pub/ruby/2.2/ru 
--2015-09-23 11:10:27--  https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.3.tar.gz
cache.ruby-lang.org をDNSに問いあわせています... 103.245.222.68
cache.ruby-lang.org|103.245.222.68|:443 に接続しています... 接続しました。
エラー: 証明書に記載されている名前 `j.ssl.fastly.net` とホスト名 `cache.ruby-lang.org` が一致しません
cache.ruby-lang.org に安全の確認をしないで接続するには、`--no-check-certificate` を使ってください。
SSL による接続が確立できません。

' なんか怒られたので言われた通りに証明書チェックしないオプションをつける(自己責任で!)'

$ wget --no-check-certificate https://cache.ruby-l 
--2015-09-23 11:10:38--  https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.3.tar.gz
cache.ruby-lang.org をDNSに問いあわせています... 103.245.222.68
cache.ruby-lang.org|103.245.222.68|:443 に接続しています... 接続しました。
警告: 証明書に記載されている名前 `j.ssl.fastly.net` とホスト名 `cache.ruby-lang.org` が一致しません
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 16626772 (16M) [application/octet-stream]
`ruby-2.2.3.tar.gz` に保存中

100%[======================================================>] 16,626,772  13.3M/s 時間 1.2s    

2015-09-23 11:10:40 (13.3 MB/s) - `ruby-2.2.3.tar.gz` へ保存完了 [16626772/16626772]

' 展開してインストール '

$ tar xvzf ruby-2.2.3.tar.gz 
$ cd ruby-2.2.3
$ ./configure 
$ make; make install

' 確認 '

$ ruby -v

  • sassのインストール

rubyインストールしたのでgemで入れます。

$ gem install sass
$ sass -v
Sass 3.4.18 (Selective Steve)

準備おっけ。

sassの基本的な使い方

基本的な流れは、sassファイルを作成し、sassコマンドでcssを出力するだけです。
簡単なのでやってみます。

style.scss
$red:#FF3399;

.red {
  color: $red;
}
sass style.scss:style.css

すると、sassがstyle.cssファイルを生成してくれます

style.css
.red {
  color: #FF3399; }

/*# sourceMappingURL=style.css.map */

気付きましたか?
sassって変数使えるんですよ!!!
これすごくないですか?
例えば、こんな依頼があったとするじゃないですか。

上司: サイトの赤って今明るいじゃん?
私: はい。普通にCSSのred使ってるのでちょっと明るいかもしれませんね。
上司: 全部さ、`#FF3399`に変えてよ。
私: えっ・・はい。。(うわーred使ってる所を全部置換するのだりーーー)
上司: 不満か?
私: いえっ!すぐに取り掛かります!
〜〜〜〜 数日後 ~~~~~~
上司: おい!なんか問い合わせページのエラー文言だけ昔の赤色のままだぞ!
私: えっ・・(やべっここだけ別のスタイルシート使ってるの忘れてたー!)

これ、sass使ってれば、置換なんてする必要なくて、$red:red$red:#FF3399にするだけで修正完了ですよ。
5秒ですよね。仕事爆速になりますよね!!

ちょっと話脱線しましたが、とにかく世界が変わるって事です。

ただ、このsassコマンド、色々便利なオプションがあるので紹介しておきますね。

sassの便利なオプション

--styleオプションで変換方法を変える

変換方法は主に4つ。
nested, expanded, compact, compressed

これから、下のsassファイルをそれぞれのオプションで出力して結果の違いを見てみます。

style.scss
$red:#FF3399;

.red {
  color: $red;

  &-.warning {
    font-weight: bold;
  }
}

  • 1. nested - sassファイルのネストの深さが引き継がれます
sass style.scss:style.css --style nested

出力結果

.red {
  color: #FF3399; }
  .red-.warning {
    font-weight: bold; }

/*# sourceMappingURL=style.css.map */
  • 2. expanded - 典型的なCSSの記述スタイルにする
sass style.scss:style.css --style expanded
style.css
.red {
  color: #FF3399;
}
.red-.warning {
  font-weight: bold;
}

/*# sourceMappingURL=style.css.map */
  • 3. compact - セレクタと属性を1行で記述してくれます
sass style.scss:style.css --style compact
style.css
.red { color: #FF3399; }
.red-.warning { font-weight: bold; }

/*# sourceMappingURL=style.css.map */
  • 4. compressed - すごく圧縮してくれる方法。可読性は悪いが軽くなる
sass style.scss:style.css --style compressed
style.css
.red{color:#f39}.red-.warning{font-weight:bold}
/*# sourceMappingURL=style.css.map */

--watchオプションで自動コンパイルする

毎回ファイルを更新する度にコンパイルするのも面倒なので自動化しましょう。

sass --watch style:scss:style:css

こうしておくと、ファイルを更新すると下のように変更を検知して勝手にコンパイルしてくれます。

>>> Change detected to: style.scss
      write style.css
      write style.css.map
  • ディレクトリ毎に指定

ちなみに、特定のディレクトリ配下をずっと監視することも可能です。
[ディレクトリ名]の部分を.(ドット)にしておけばカレントディレクトリを監視対象に出来ます。

sass --watch [ディレクトリ名]
  • 他のオプションと併用

また、先ほどのstyleオプション等他のオプションと一緒に指定することも可能です。

sass --watch . --style compact
  • フォルダ毎指定

普通は、sassディレクトリとcssディレクトリを作って、sassフォルダで作ったファイルをcssディレクトリに出力したいでしょう。
それも可能です。

sass --watch sass:css
  • 出力ファイル名

sassコマンドで、対象のscssファイルと出力するcssのファイル名を指定しなければ、自動的にscssのファイル名で出力されます。

hoge.scssファイルを作るとこんな感じで、hoge.cssが出力されます。

>>> New template detected: hoge.scss
      write ./hoge.css
      write ./hoge.css.map

Sass記法とSCSS記法の違い

すいません。これまでずっとCSCCで書いてしまっていたんですが、ここで一旦SASS記法も紹介しておきます。
ちなみに、そんなに変わらないですが、私はCSSっぽく書けるSCSS記法の方が気に入ってます。

  • SASSとSCSS記法の違い

(わかりやすくするためにCSSも書いておきます)

- SCSS記法 SASS記法 CSS
波括弧{} 必要 不要(半角スペーサー2個のインデントでブロックを表します) 必要
セミコロン; 必要 不要 必要
コロン:のあとのスペース 不要 必要 不要
ミックスイン @mixin =
インクルード @include +
拡張子 .scss .sass .css

じゃあちょっと、ここで同じCSSをSASS記法とSCSS記法で書くとそれぞれどう変わるかを見てみましょう。

  • SASS記法
$orange:orange
$red:red

= btn($radius, $bg_color)
  border-radius: $radius
  background: $bg_color

.red
  color: $red

.btn-warning
  +btn("3px", $orange)

.btn-error
  +btn("3px", $red)
  • SCSS記法
$orange:orange;
$red:red;

@mixin btn($radius, $bg_color) {
  border-radius:$radius;
  background:$bg_color;
}

.red {
  color:$red;
}

.btn-warning {
  @include btn(3px,$orange);
}

.btn-error {
  @include btn(3px, $red);
}
  • 出力されるcss
.red {
  color: red; }

.btn-warning {
  border-radius: "3px";
  background: orange; }

.btn-error {
  border-radius: "3px";
  background: red; }

どちらも同じCSSが吐き出されているのがわかります。
個人的には、癖で波括弧書いたり、セミコロンを書いたりしちゃうので、SCSS記法の方が好きです。

さぁ、では基礎がわかった所でいよいよSASSのすごい所を色々と見ていきましょう。

Sassの最強機能7選

1. 変数

これはもう何度も出てますが、Sassでは変数が使えます。

$red: red;
$blue: blue;

.red {
  color: $red;
}

.blue {
  color: $blue;
}

便利ですよね。

2. ネストが使える

さて、今までCSSでは、div#main直下のaタグのimgタグに対して指定するときは、#main > a > imgのようにセレクタを指定してました。

これ面倒なのは、#mainaimgそれぞれにスタイルを当てたい時とか、セレクタをを合計で4つ書かないといけなかったんですよね。

Sassを使えばこんな面倒な書き方はしなくて良いのです。

#main {
  width: 200px;
  height: 100px;

  & a {
    & img {
      width: 50px;
      height: 50px;
    }
  }
}
#main {
  width: 200px;
  height: 100px; }
  #main a img {
    width: 50px;
    height: 50px; }

3. 名前空間でネストが可能

同一の名前空間を持つプロパティの場合、この名前空間でネストが可能です。

.title {
  font: {
    family: family;
    size: 1.5em;
    color: blue;
  }
  border: {
    radius: 4px;
    color: red;
  }
}
.title {
  font-family: family;
  font-size: 1.5em;
  font-color: blue;
  border-radius: 4px;
  border-color: red; }

素晴らしすぎる・・・

4. @importを使って別のファイルを読み込める

importはCSSでも使えました。
ただし、それをやるには、style.cssmain.cssを2つ作って、style.cssmain.cssをimport。とかやる必要がありました。
これはパフォーマンス的な観点であまりよろしくありません。

というのも、HTTPのリクエストはstyle.cssとmain.cssの2つ分のリクエストが走りますので、リクエストが多くなればなるほど負荷高騰につながりやすいのです。

じゃあSassだと何がいいの?っていうと、Sassの場合は別のSassファイルをimportすることになりますので、いくらimportしてようが最終的に出力されるCSSファイルは1つになります。
つまり、どんだけimportしてようがHTTPのリクエストは1回で済みます。
(あまりimportしすぎればその分CSSのファイルが大きくなって負荷が上がってしまうと思いますが・・)

実際にやってみます。

fuga.scss
body {
  width: 100%;
}
hoge.scss
@import "fuga.scss";

.title {
  font: {
    family: family;
    size: 1.5em;
    color: blue;
  }
  border: {
    radius: 4px;
    color: red;
  }
}
hoge.css
body {
  width: 100%; }

.title {
  font-family: family;
  font-size: 1.5em;
  font-color: blue;
  border-radius: 4px;
  border-color: red; }

ちゃんと読みめてますね。
ちなみに、importは、下のようにも書くことが出来ます。

@import url("style.scss");

5. mixinを使ってスタイルの使い回しが可能

これ、個人的にかなりアツいです。

何がアツいって、まず共通で使うようなスタイルを色んな所で使えるという点。そして引数が渡せるのです!!!

やってみましょう。

@mixin circle($width:50px, $height:50px, $bg_color:white) {
  width: $width;
  height: $height;
  background: $bg_color;
}

.box1 {
  @include circle(100px, 100px, red);
}

.box2 {
  /* 引数を指定しなければデフォルト値が適用される */
  @include circle();
}
.box1 {
  width: 100px;
  height: 100px;
  background: red; }

.box2 {
  /* 引数を指定しなければデフォルト値が適用される */
  width: 50px;
  height: 50px;
  background: white; }

6. 四則演算が・・・できる!!

やばくないっすか?
よく、ボックスを横並びにする時なんかに、「え〜と・・・3等分だから、1/3で・・33.3333%。4等分だから・・25%か」とかってやってたのが考える必要なくなるんです。

.div1, .div2, .div3 {
  float: left;
  width: (100%/3);
}

.box1, .box2, .box3, .box4 {
  float: left;
  width: (100%/4);
}
.div1, .div2, .div3 {
  float: left;
  width: 33.33333%; }

.box1, .box2, .box3, .box4 {
  float: left;
  width: 25%; }

便利すぎる・・・・!!!!

7. 制御構文が使える!!!!!

制御構文って言うと難しく聞こえますが、単純に条件分岐とか繰り返しですね。
ifとかforがcssで使えるって事です。

なんかforとかは使いみちがわかるんですが、ifを使う場面がよくわかってないです。

とりあえず、@if, @for, @each, @whileの4つは紹介しておきます。

$type: top;

.main {
  @if $type == top {
    padding: 10px;
  } @else if $type == fotter {
    padding: 5px;
  } @else {
    padding: 15px;
  }
}
.main {
  padding: 10px; }

.media配下の.img-1, .img-2とかにそれぞれ連番の画像を背景にしたいときとか

.media {
  @for $i from 1 through 3 {
    .img-#{$i} {
      background-image: url("/img-#{$i}.png");
    }
  }
}
.media .img-1 {
  background-image: url("/img-1.png"); }
.media .img-2 {
  background-image: url("/img-2.png"); }
.media .img-3 {
  background-image: url("/img-3.png"); }
  • each

eachは配列が使えて便利!!

.media {
  $image_lists: bird, dog, cat;

  @each $value in $image_lists {
    .img-#{$value} {
      background-image: url("/img-#{$value}.png");
    }
  }
}
.media .img-bird {
  background-image: url("/img-bird.png"); }
.media .img-dog {
  background-image: url("/img-dog.png"); }
.media .img-cat {
  background-image: url("/img-cat.png"); }
  • while
$i: 1;
@while $i < 5 {
  .item-#{$i} { width: 2em * $i; }
  $i: $i + 1;
}

.item-1 {
  width: 2em; }

.item-2 {
  width: 4em; }

.item-3 {
  width: 6em; }

.item-4 {
  width: 8em; }

まとめ

※ 9月24日現在、まだSass(SCSS)部分までしか書いてないです。明日までにはLESSの方も追記します。
また、時間が間に合えばもっとこれらのメタ言語を使って高速に開発が可能になるgulpとかについても書いてみます。