Sassで色をURLエンコードする関数

Sass 3.3で導入される予定のものではなんといっても--sourcemapオプションが注目。でももちろんそれだけじゃなくて、文字列から文字列を探すstr-index()関数とか文字列から一部切り出すstr-slice()関数などといった文字列関係の関数の充実もある。これらの新文字列関数を利用すると、以下で取り上げる色の簡易URLエンコードを行う関数のような、文字列をちょっといじるというようなことをCustom Functionを作ることなく行えるようになる。

以下はSass 3.3.0.alpha.218 (Bleeding Edge)での話なので、3.3の正式リリースでは動く保証はない。

// encode-color() - Encode color by percent encoding
//
// @param {color} $color Color that you want to encode
// @return {string}
@function encode-color($color) {
  $str_color: "" + $color;

  @if (str-index($str_color, "#") == 1) {
    $str_color: "%23" + str-slice($str_color, 2);
  }

  @if (str-index($str_color, "rgba") == 1) {
    $str_color: "rgba(" + red($color) + "%2C" + green($color) + "%2C" + blue($color) + "%2C" + alpha($color) + ")";
  }

  @return $str_color;
}

str-index()str-slice()関数は文字列専用で色を投げるとエラーになるので、まずは色に空文字を連結することによって型をキャストすることろから。今までは型キャストが必要なケースはほとんど無かったけど、これからは使う機会増えそう。

Sassで色は大体#で始まる16進数のRGBで扱われる(hsl()とかで定義しても)ので、まずはそれをチェック。str-index()関数は一文字目を1として見つかった位置を返す(見つからなかったら0)ので、#が一文字目にあるかどうかで確認する。見つかった場合は2文字目以降を切り出して#をURLエンコードした%23をくっつける。

透明度付きの場合はrgba()で扱われるので、rgbaを探す。見つかったらRGBそれぞれとalphaをビルトイン関数で1つずつ取り出し、URLエンコードが必要な,%2Cにして連結している。

これらにマッチしなかった場合は色キーワードなのでそのまま返す。

.test {
  content: "#{encode-color(#336699)}"; // %23369
  content: "#{encode-color(rgb(51, 102, 153))}"; // %23369
  content: "#{encode-color(rgba(51, 102, 153, 0.2))}"; // rgba(51%2C102%2C153%2C0.2)
  content: "#{encode-color(beige)}"; // beige
}

このテストはうまくいったのでこれでだいたい大丈夫そう。


CSSではそもそも数値や色を主に扱うので、Sass 3.3からのstr-*()関数はあまりダイレクトには役には立たなそう。だけど自前で関数を書く時などには大きな力を発揮しそうな感じだ。3.3のCHANGELOGに書いてある通り、他に文字列に文字を挿入するstr-insert()や文字列を大文字(小文字)に変換するto-upper(lower)-case()関数なんかがある。