Edited at

CSS→Stylusを学ぶまでの軌跡② SASS

More than 3 years have passed since last update.


SASS

SASS


  • CSSを効率的に書く為の機能

  • .sass(Ruby/Haml系)

  • .scss(CSS)→CSSらしく記述でき、デザイナでも修正できるので主流となっている

⇒さらに詳しく


  • HTMLによるマークアップを簡略化するためのHamlから派生。

  • コンパイラーはRubyで実装。

  • SCSS(.scss)ファイルのCSSファイルへの変換。

  • サーバーサイドでの利用を想定。

  • 非常に豊富な機能を持っており、条件分岐や繰り返しによる柔軟な制御が可能。

  • 日本語のドキュメントが多く、開発コミュニティが安定。


  • Compassフレームワークが使えて便利?


前提知識


  • HTML/CSS/CSS3

  • Unix Command


公式サイト/学習サイト


SASS & SCSS のメリット


  • 変数が使える。

  • CSSの継承をネストでまとめられる。

  • ネームスペースでネストできる。

  • Partial(@importでCSSファイルを1つにまとめられる。)


  • @mixin@includeでスタイルを使い回せる。@mixinでは引数も使える。

  • 算術演算子で値の加減乗除ができる。

  • 別の単位同士で演算できる。

  • 条件分岐(@if)や繰り返し(@for, @while, @each)処理ができる。

  • コンパイルオプションで変換の仕方を変えられる。


変換の流れ


  • SCSSをCSSに変換し、「css」フォルダに保存する。

  • cssに保管されたCSSをindex.htmlでインポートする。


フォルダ構成

 +-index.html

+-scss(記述ファイル保存先)
+-main.scss
+-css(変換後ファイル保存先)
+-main.css
+-main.css.map


セレクタに変数を代入


style.scss

@h1-color:red;

@h2-color: darken(@h1-color, 10%);
@h1-size: 24px;
@h2-size: @h1-size - 8px;

@header: h;
@color : color;
@dir : "/img";

@{header}1{
font-size: @h1-size;
@{color}: @h1-color;
}

@{header}2 {
font-size: @h2-size;
@{color}: @h2-color;
background: url("@{dir}/bg.png");
}



style.css

h1 {

font-size: 24px;
color: red;
}
h2 {
font-size: 16px;
color: #cc0000;
background: url("/img/bg.png");
}


ネスト/疑似クラス(&)


style.scss

header {

font-size: 18px;
a {
color: red;
&:hover {
color: green;
}
}
}

// .button-ok, .button-ng
.button {
&-ok {
color: green;
}
&-ng {
color: red;
}
}



style.css

header {

font-size: 18px;
}
header a {
color: red;
}
header a:hover {
color: green;
}
.button-ok {
color: green;
}
.button-ng {
color: red;
}


簡単な変換例


sample.sass

body

color: #000


sample.scss(CSSに近い)

body{

color:#000;
}

 ↓ コンパイル


sample.css(CSSに近い)

body {

color:#000;
}


SCSS記法とSASS記法とCSSの違い

SCSS記法
SASS記法
CSS

波括弧 {}
必要
不要
インデントで
ネスト
必要

セミコロン(;)
必要
不要
必要

コロン(:)の後にスペース
不要
必要
不要

ミックスイン
@mixin
=
なし

インクルード
@include
+
なし

拡張子
.scss
.sass
.css


環境(インストール)


console

# Ruby インストール状態の確認(インストール済)

$ ruby -v
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin13]
$ sudo gem update --system
$ sudo gem install sass
Fetching: sass-3.4.18.gem (100%)
Successfully installed sass-3.4.18
Parsing documentation for sass-3.4.18
Installing ri documentation for sass-3.4.18
Done installing documentation for sass after 6 seconds
1 gem installed
$ sudo gem list sass

*** LOCAL GEMS ***

sass (3.4.18)



SCSS ⇒ CSS 変換


main.scss(変換元ファイル)

/**

* 変換後、反映されるコメント
*/

// 変換後、反映されないコメント
#main { /*親要素*/
width : 90%; /*属性*/
p { /*子要素*/
font-size:16px;
a {
text-decoration: none;
/*&=入れ子の構造でhoverが有る場合の親要素を指す。*/
&:hover {
font-weight: bold;
}
}
}
}


console

# sass (オリジナル):(出力先)

$ sass scss/main.scss:css/main.css
# 字下げが綺麗になる。
$ sass --style expanded scss/main.scss:css/main.css



  • nested/expanded/compact/compressedのオプションを使用可。


main.css(変換先ファイル)

@charset "UTF-8";

/**
* 変換後、反映されるコメント
*/

#main {
/*親要素*/
width: 90%;
/*属性*/
}
#main p {
/*子要素*/
font-size: 16px;
}
#main p a {
text-decoration: none;
/*&=入れ子の構造でhoverが有る場合の親要素を指す。*/
}
#main p a:hover {
font-weight: bold;
}

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



SCSSに変更がある場合、自動的に変換する。


console

$ sass --style expanded --watch scss:css

>>> Sass is watching for changes. Press Ctrl-C to stop.
[Listen warning]:
Listen will be polling for changes. Learn more at https://github.com/guard/listen#polling-fallback.
>>> Change detected to: scss/main.scss
write css/main.css
write css/main.css.map
# Ctrl+Cで終了


変数の使用


  • 変数は「$変数名:;」で定義する。


main.scss

/**

* 変数:データにつけるラベル
* データ型(数値、文字列、真偽、色、リスト)
* 四則演算も可能
*/

$baseFontSize: 14px;
#main {
width : 90%;
p {
font-size:$baseFontSize;
.sub {
font-size: $baseFontSize - 2px;
}
}
}


main.css

@charset "UTF-8";

/**
* 変数:データにつけるラベル
* データ型(数値、文字列、真偽、色、リスト)
* 四則演算(+ - * /) も可能
*/

#main {
width: 90%;
}
#main p {
font-size: 14px;
}
#main p .sub {
font-size: 12px;
}

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



変数の埋込み


  • 変数の埋込みは「$FOO+$BAR」で連結する。もしくは「#{$FOO}#{$BAR}」のように埋込む。

  • 「#{\$FOO\$BAR}」とコーディングしたところ、\$FOOと\$BARの間に半角スペースが開いたため、この記述は不可?


main.scss

/**

* 文字列変数を埋込む
*/

$imageDir: "../img/";
$image: "bg.png";

#main {
width : 90%;
p {
font-size:#{12 + 12}px;
//background: url($imageDir + "bg.png");
background: url("#{$imageDir}#{$image}");
}
}



main.css

@charset "UTF-8";

/**
* 文字列変数を埋込む
*/

#main {
width: 90%;
}
#main p {
font-size: 24px;
background: url("../img/bg.png");
}

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



色を扱う(Sass Built-in Functions)


main.scss

/**

* 色を埋込む
*/

$brandColor: red;
// $brandColor: #ff0000;
// $brandColor: rgb(255, 0, 0, 0.9);

#main {
width : 90%;
p {
font-size:14px;
// lighten, darken
color: lighten($brandColor, 30%);
}
}



分岐(@if, @else


main.scss

$debugMode: true;

$x: 30;

#main {
@if $debugMode == true { // == , != , <=, >=
color: red;
} @else {
color:green;
}
p {
@if $x > 20 { color: red; }
}
}



main.css

#main {

color: red;
}
#main p {
color: red;
}

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



ループ(@for, @while


main.scss

@for $i from 10 through 14 {

.fs#{$i} { font-size: #{$i}px; }
}

$i: 10;
@while $i <= 14 {
.ws#{$i} { font-size: #{$i}px; }
$i: $i + 1;
}



main.css

.fs10 {

font-size: 10px;
}

.fs11 {
font-size: 11px;
}

.fs12 {
font-size: 12px;
}

.fs13 {
font-size: 13px;
}

.fs14 {
font-size: 14px;
}

.ws10 {
font-size: 10px;
}

.ws11 {
font-size: 11px;
}

.ws12 {
font-size: 12px;
}

.ws13 {
font-size: 13px;
}

.ws14 {
font-size: 14px;
}

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



リスト


main.scss

$animals: cat, dog, tiger;

@each $animal in $animals {
.#{$animal}-icon {background: url("#{$animal}.png");}
}

@each $animal in cat, dog, tiger {
.#{$animal}-icon {background: url("#{$animal}.png");}
}



main.css

.cat-icon {

background: url("cat.png");
}

.dog-icon {
background: url("dog.png");
}

.tiger-icon {
background: url("tiger.png");
}

.cat-icon {
background: url("cat.png");
}

.dog-icon {
background: url("dog.png");
}

.tiger-icon {
background: url("tiger.png");
}

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



関数(@function)・デバッグ表示(@debug

関数内の変数はプライベード変数となっている事に注意する。


main.css

$totalWidth: 940px;

$columCount: 5;

@function getColumnWidth($width, $count) {
$padding: 10px;
$columnWidth: floor(($width - ($padding * ($count - 1))) / $count);
@debug $columnWidth;
@return $columnWidth;
}

.grid {
float: left;
width: getColumnWidth($totalWidth, $columCount);
}



main.css

.grid {

float: left;
width: 180px;
}

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



ファイル分割(Partial)


_settings.scss

$totalWidth: 940px;

$columCount: 5;


_functions.scss

@function getColumnWidth($width, $count) {

$padding: 10px;
$columnWidth: floor(($width - ($padding * ($count - 1))) / $count);
@debug $columnWidth;
@return $columnWidth;
}


main.scss

@import "settings";

@import "functions";

.grid {
float: left;
width: getColumnWidth($totalWidth, $columCount);
}



@mixin & @includex


main.scss

@mixin round ($radius) {

border-radius: $radius;
}

.label {
font-size: 12px;
@include round(5px);
}



main.css

.label {

font-size: 12px;
border-radius: 5px;
}

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



継承(@extend


main.scss

// @extend(継承)

// .errorMsg, .warningMsg

.msg {
font-size: 12px;
font-weight : bold;
padding: 2px 4px;
color: white;

}
.errorMsg {
@extend .msg;
background: red;
}

.warningMsg {
@extend .msg;
background: orange;
}



main.css

.msg, .errorMsg, .warningMsg {

font-size: 12px;
font-weight: bold;
padding: 2px 4px;
color: white;
}

.errorMsg {
background: red;
}

.warningMsg {
background: orange;
}

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