[Sass] Sass 3.2で実装された新機能がヤバい

8/10に3.2、8/15にバグフィックスした3.2.1がリリースされて
ただでさえヤバイくらい高機能なSassがますますパワーアップした。
Sass信者のみなさんはすでにお使いでしょうか?


晒したソースはオンラインコンパイラで試せます。

jsdo.itも対応してます。

@content

これはmixinにブロックコンテンツを渡せるようにする合言葉。
mixinを作る時、渡されたブロックコンテンツを入れたい場所に@contentを配置すると

@mixin iphone {
  @media only screen and (max-width: 480px) {
    @content;
  }
}

@includeするときに波括弧で括ってコンテンツを渡せるようになる。

@include iphone {
  body { color: red }
}

コンパイルすればこのとおり、@mixinの内容+渡した内容が合わさったスタイルに。

@media only screen and (max-width: 480px) {
  body {
    color: red;
  }
}

普通の引数が使えなくなるのかというとそうでもなく、

@mixin max-width-query($width: 480px) {
  @media only screen and (max-width: $width) {
    @content;
  }
}
 
@include max-width-query(320px) {
  body { color: red }
}

問題なく使える。

@media only screen and (max-width: 320px) {
  body {
    color: red;
  }
}

%placeholder

プレースホルダーセレクタはドットの代わりに%を使う@extend専用のメタセレクタ。
@includeするとエラーになる。

@mixinが抱えてたモヤモヤ感とか@extendする為だけにクラスを作る無駄を一掃してくれる神機能で、
それがどうアレなのかは@takazudoさんのスライドがマジヤバかったんで説明は割愛させていただく。

使い方はとても単純明快で、ドットを%に置き換えればプレースホルダーセレクタになる。

.blueText {
 color:blue;
}
 
#header {
   background:white;
   @extend .blueText;
}

#footer {
  background:gray;
   @extend .blueText;
}
/* .blueText は必要ないのに書き出される */
.blueText, #header, #footer {
  color: blue; }

#header {
  background: white; }

#footer {
  background: gray; }

ドット→%

%blueText {
 color:blue;
}
 
#header {
   background:white;
   @extend %blueText;
}

#footer {
  background:gray;
   @extend %blueText;
}
/* blueTextが消える */
#header, #footer {
  color: blue; }

#header {
  background: white; }

#footer {
  background: gray; }

@extendしかされてないセレクタを自動判別するという手もあったんじゃないかと思うんだけどね。

Variable Arguments

可変引数。って直訳でいいんだろうか。

box-shadowやbackgroundなどの重複指定出来るプロパティの値でカンマを使うものがいくつかある。
Sassはスペースまたはカンマで区切られた値はリストとして認識していて、
リスト用関数まで用意していたりするのだが、カンマ区切りのリストを引数で渡そうとする時に問題が起きていた。

引数が1つしか定義されていないミックスインに

@mixin box-shadow($shadows) {
  -moz-box-shadow: $shadows;
  -webkit-box-shadow: $shadows;
  box-shadow: $shadows;
}

カンマ区切りの値を渡して@includeすると、引数の数が合わないというエラーが出る。

.shadows {
  @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}
//=> Mixin box-shadow takes 1 argument but 2 were passed.

引数として渡された値にカンマがあるときは「1つのリスト」ではなく「いくつかの引数」として扱われる。
クォートで囲うとエラーは消えるが、コンパイル後のCSSにもクォートが入ってしまう。
文字列で渡してクォート除去する関数(unquote)で対処するくらいしか手が無かったんだが、とうとう修正が入った。

カンマ区切りの配列を渡したいmixinの引数の変数名に … (ドット3つ)を付け足すだけ!

@mixin box-shadow($shadows...) {
  -moz-box-shadow: $shadows;
  -webkit-box-shadow: $shadows;
  box-shadow: $shadows;
}

いくつでもカンマで区切れるようになるが、
ドット3つつけた引数の後ろには何も渡せなくなるので注意。

@mixin box-shadow($shadows..., $option) //=> Error!! 

includeの時でもOK

引数を渡す時にドット3つつけてもいい。
(値がリスト形式のものに限られる)

@mixin colors($fg, $bg, $border) {
  color: $fg;
  background-color: $bg;
  border-color: $border;
}

$box-colors: black, yellow, blue;
.box { @include colors($box-colors...); }

#{} が@規則でも使えるように

つまり @import、@charset、@font-face、@keyframes、@media、 @page、@document、@supportsで使える。
中じゃなくて外側で。
変数厨になってしまいそうだ…。

@mediaの場合

$media: screen;
$feature: -webkit-min-device-pixel-ratio;
$value: 1.5;
 
@media #{$media} and ($feature: $value) {
  ...
}

@font-faceの場合

ガワがないから例にならないんだけど一応。
w3cschoolsのサンプルをSass化してみた。

$font-name:myFirstFont;
$font-file:'Sansation';
$use-bold:false;
 
@font-face {
  $weight:'_Light';
 
  @if $use-bold == true {
    font-weight:bold;
    $wieight:'_Bold';
  }
  font-family: $font-name;
  src: url($font-file + $weight + '.ttf'),
       url($font-file + $weight + '.eot');
 
}
@font-face {
  font-family: myFirstFont;
  src: url("Sansation_Light.ttf"), url("Sansation_Light.eot");
}

@keyframes

名前を変数にできる。
フレームの指定はバーセントを使った数値なので、
#{$step}% とか #{$step + %}と書いてもコンパイルエラーになるけど小技を使えば通る。

しかしプロパティであるkeyframesには使えないようだった。
@-webkit-#{$property} → コンパイラが止まる

$sample-anim:sample;
@-webkit-keyframes $sample-anim {
 
  $top:0px;
  $left:0px;
 
  @each $step in 0, 50, 100 {
    $top:0px + ($step * 2);
    $left:0px + ($step * 2);
 
    #{$step + 0%} {
      top:$top;
      left:$left;
    }
  }
}
@-webkit-keyframes sample {
  0% {
    top: 0px;
    left: 0px; 
  }
 
  50% {
    top: 100px;
    left: 100px;
  }
 
  100% {
    top: 200px;
    left: 200px;
  } 
}

mixinにすればベンダープレフィックスつける手間がちょっと減る。

@mixin keyframes($name) {
 
  @-webkit-keyframes $name {
    @content;
  }
 
  @-moz-keyframes $name {
    @content;
  }
 
  @keyframes $name {
    @content;
  }
}
 
@include keyframes(sample) {
   $top:0px;
   $left:0px;
 
   @each $step in 0 50 100 {
    $top:0px + ($step * 2);
    $left:0px + ($step * 2);
 
    #{$step + 0%} {
      top:$top;
      left:$left;
    }
  }
}

@eachもmixinに含められるといいなあと思うんだけど、
中に@content入れても変数が渡せないから無理でした。

属性セレクタで#{} を使うとエラーになるバグの修正

クォートはあってもなくてもおkな存在に。

@each $type in text {
    input[type=#{$type}] {
 
    }
}

ie_hex_str

渡された色をIE向けのhex文字列に変換する関数。
出番はfilterプロパティくらいだろうか…

ie-hex-str(#abc) => #FFAABBCC
ie-hex-str(#3322BB) => #FF3322BB
ie-hex-str(rgba(0, 255, 0, 0.5)) => #8000FF00

CSS4セレクタに対応

まだEditor’s Draftだというのに CSS4 selectors を全部サポート。
ブラウザの対応が待ち遠しいな…(遠い目)

開発者のブログにサンプルがあったお。

header %component {
  margin-bottom: 0;
}
%component! ol {
  padding-left: 20px;
}

section! .widget { @extend %component; }
header section! .widget {
  margin-bottom: 0; }

section! .widget ol,
section! ol .widget {
  padding-left: 20px; }

プレースホルダーセレクタはメタのセレクタなので普通のクラスっぽく扱えるわけで、
親の指定だとか子の指定だとかも出来たりする。ってのと
CSS4の!が問題なく使えてるということが分かりますね。

@mixinと@functionをネストした時の挙動

@mixinの中で@functionを使った時は、@mixinと同じスコープにある@functionが実行の対象になる。

@mixin foreground {
  color: color();
}
.not-nested {
  @function color() { @return red; } //スコープが違う
}

同じスコープにfunctionが見つからないときは関数がそのまま出力されるがエラーにはならない。

.nested {
  color: color();
}

このようにスコープが違うとスルーされるので、includeの前にfunctionを再定義してもoverrideされないのである。

@mixin foreground {
  color: color();
}

@function color() { @return red; }

.not-nested {
  @include foreground;
}
.nested {
  @function color() { @return blue; }
  @include foreground;
}
.not-nested { color: red; }
.nested { color: red; }

グローバルな変数であればincludeの前に変更すればその値で実行出来るけど、
@functionはオーバーライドはされなくて、「.nestedの中で定義された関数」になるので、スコープが違う別の関数という扱いになる。
外のスコープにある関数を定義しているmixinは中のスコープを参照出来ないため、上記例ではcolorが全てredになる。

nullデータタイプ

nullはmixinとかfunctionで使う変数のデフォルト値やオプションの値として大変優秀です。
変数の値がnullのままだったらどうなるかというと、その変数を使っているプロパティは出力されないのです。

$color: null;
div {
  width: 23px;
  color: $color;
  border: 2px solid $color;
}
div {
  width: 23px;
  border: 2px solid;
}

「[Sass] Sass 3.2で実装された新機能がヤバい」への4件のフィードバック

  1. ピンバック: SASSメモ1 | log

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください