Milk+ea

Weblog Is My Hobby.

【Sass】開始位置,色,位置の順番で書けるgradientのMixinを作ってみた

僕的に分かりやすく書けるようにした結果こんな感じのものができました。
以下のコードはすべてSASS形式です。
SCSS形式に書きなおそうと思ったけどツカレタョ…。
Ultimate CSS Gradient Generator - ColorZilla.comというジェネレーターサイトを参考にしました。
ということで、このサイトと同じような感じで出力されます。

使い方

/*
 * linear-gradient
 * l-gradient(開始位置, 色List, 位置List)
 */
+l-gradient(top, #000 #333 #666 #999 #ccc #fff, 0% 20% 40% 60% 80% 100%)

/*
 * radial-gradient
 * r-gradient(色List, 位置List)
 */
+r-gradient(#000 #333 #666 #999 #ccc #fff, 0% 20% 40% 60% 80% 100%)
  • 開始位置には(left, top, -45deg, 45deg)のどれかを指定します。
  • 色と位置はSassのリスト形式(カンマなし)で書いていきます。色の1番目と位置の1番目がペアになって処理されます。

出力

// linear-gradient
{
background: black;
background: -webkit-linear-gradient(top, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
background: -moz-linear-gradient(top, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
background: -o-linear-gradient(top, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
background: -ms-linear-gradient(top, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
background: linear-gradient(to bottom, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#FF000000", endColorstr="#FFFFFFFF", GradientType=0);
}

// radial-gradient
{
background: black;
background: -webkit-radial-gradient(center, ellipse cover, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
background: -moz-radial-gradient(center, ellipse cover, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
background: -o-radial-gradient(center, ellipse cover, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
background: -ms-radial-gradient(center, ellipse cover, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
background: radial-gradient(ellipse at center, #000000 0%, #333333 20%, #666666 40%, #999999 60%, #cccccc 80%, #ffffff 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#FF000000", endColorstr="#FFFFFFFF", GradientType=1);
}

-webkit-gradientはAndroidとかを想定してないなら表示しないようしました。
コードの$Androidというのをtrueにすると-webkit-gradientも出力されます。

Mixinコード

思ったより長くなってしまったので次のページで。

$pfull : -webkit-, -moz-, -o-, -ms-, ''

// 古いwebkit系の開始位置を返す
@function webkit-start($start)
  @if $start == 'left'
    @return 'left top, right top'
  @else if $start == 'top'
    @return 'left top, left bottom'
  @else if $start == -45deg
    @return 'left top, right bottom'
  @else if $start == 45deg
    @return 'left bottom, right top'

// 古いwebkit系のcolor-stopを返す
@function webkit-gradient($percents, $colors)
  $to     : length($percents)
  $result : null
  @for $i from 1 through $to
    $percent   : nth($percents, $i)
    $color     : nth($colors, $i)
    $color-stop: 'color-stop(' + $percent + ', ' + $color + ')'
    $result    : append($result, unquote($color-stop), comma)
  @return $result

// ベンダープレフィックスなしの開始位置を返す
@function normal-start($start)
  @if $start == 'left'
    @return 'to right'
  @else if $start == 'top'
    @return 'to bottom'
  @else if $start == -45deg
    @return 135deg
  @else if $start == 45deg
    @return $start

// IE用のfilterプロパティで使うGradientTypeを返す
@function gradient-type($start)
  @if $start == 'top'
    @return 0
  @else
    @return 1

/*
 * l-gradient
 * $base-start: 開始位置 left or top, -45deg, 45deg
 * $colors    : 色のリスト
 * $percents  : 位置リスト
 * $android   : -webkit-gradientを使うかどうか
 */
=l-gradient($base-start, $colors, $percents, $android: false)
  $gradation      : zip($colors, $percents)
  $webkit-start   : webkit-start($base-start)
  $webkit-gradient: webkit-gradient($percents, $colors)
  $normal-start   : normal-start($base-start)
  $start-color    : nth($colors, 1)
  $end-color      : nth($colors, length($colors))
  $filter         : unquote('progid:DXImageTransform.Microsoft.gradient(startColorstr="' + ie-hex-str($start-color) + '", endColorstr="' + ie-hex-str($end-color) + '", GradientType=' + gradient-type($base-start) + ')')

  background: $start-color
  @each $p in $pfull
    @if $p == '-webkit-'
      @if $android == true
        background: #{ $p }gradient(linear, unquote($webkit-start), $webkit-gradient)
    @if $p == ''
      background: linear-gradient(unquote($normal-start), $gradation)
    @else
      background: #{ $p }linear-gradient($base-start, $gradation)
  filter: $filter

/*
 * r-gradient
 * $colors    : 色のリスト
 * $percents  : 位置リスト
 * $android   : -webkit-gradientを使うかどうか
 */
=r-gradient($colors, $percents, $android: false)
  $gradation      : zip($colors, $percents)
  $webkit-gradient: webkit-gradient($percents, $colors)
  $start-color    : nth($colors, 1)
  $end-color      : nth($colors, length($colors))
  $filter         : unquote('progid:DXImageTransform.Microsoft.gradient(startColorstr="' + ie-hex-str($start-color) + '", endColorstr="' + ie-hex-str($end-color) + '", GradientType=1)')

  background: $start-color
  @each $p in $pfull
    @if $p == '-webkit-'
      @if $android == true
        background: #{ $p }gradient(radial, center center, 0px, center center, 100%, $webkit-gradient)
    @if $p == ''
      background: radial-gradient(ellipse at center, $gradation)
    @else
      background: #{ $p }radial-gradient(center, ellipse cover, $gradation)
  filter: $filter

効率悪いからか長くなってしまった。
というかfilterって最初と最後の色しか使えないので別にしたほうがいい気がしてきた。
反射光とか入れて作る人は、最初と最後が同じような色になってアルェ~って、ならないですかね(ボタンとか)。

関数とか調べながらやったので時間が結構掛かったー。