Sassで色空間『HSB』を扱う関数を作った話
- 2015/07/17
- atsuko.a
こんにちは、フロントエンドエンジニアのあつこです(ΦωΦ)
先日どうしてもSassでHSBを使用したかった際の、経緯と対処法を紹介します。
もくじ
- RGBとHSLとHSB
- 何故HSBなのか
- RGBとHSBの相互変換関数を書く
- まとめ
RGBとHSLとHSB
そもそもHSBは色空間の一種で、RGBやHSLと同じように3つの要素から色を特定する方法です。
ここでは代表的な色空間である、RGBとHSLとHSBについてざざっと紹介します。
RGB
WEB屋さんにはお馴染みの加法混色です。
赤(Red)緑(Green)青(Blue)値はそれぞれ0→255の間で設定し、すべて足すと白になります。
HSL
色相(Hue)彩度(Saturation)輝度(Lightness)の3要素から成る色空間。
色相は0°→360°の角度、彩度と輝度は0%→100%(もしくは0→255)の間で設定します。
CSS3で色の指定として使用できるようになりました。
また、SassにもHSLを変換する関数があります。
HSB
色相(Hue)彩度(Saturation)明度(Brightness)の3要素から成る色空間。
色相は0°→360°の角度、彩度と明度は0%→100%(もしくは0→255)の間で設定します。
フォトショやsketch・FireworksなどのグラフィックツールにはRGB・CMYKの他にHSBでの色指定ができる機能があるようです。
明度を「Value」とし「HSV」と呼ぶこともあるようです
何故HSBなのか
HSLとHSBの指定方法は似ていますが、考え方が異なる為同じ色を表現する場合で数値が異なります。
HSL
- 彩度(S値):100%を純色とし、0%になるにつれ灰色になっていく
- 輝度(L値):100%を白、0%を黒とし、中間の50%を純色とする
HSB
- 彩度(S値):100%を純色とし、0%になるにつれ白色になっていく
- 明度(B値):100%を純色とし、0%になるにつれ黒色になっていく
図を並べてみると明確ですね。
で、上でも書いたように多くのグラフィックツールではHSBが使えることが多いです。
ボタンを作るときなど、
- 影はベース色に対して明度を25下げる
- ホバーはベース色に対して彩度を10上げる
といった方法で作ると、同じテイストの違う色のボタンを作る時に便利です。
RGBとHSBの相互変換関数を書く
HSBが便利なのは有難いのですが、Sass(CSS)ではHSBは使えないので、どうにか変換する関数を作りました。
手順としてはこんな感じ、、、
- RGBを元にHSBそれぞれの値を出す…色A
- 色Aのそれぞれの値に対して、適宜計算する…色B
- 色Bを元にしてRGBの値を出す
RGBとHSBの相互変換には決まった式があるのでそれをもごもごと関数にしていきます。
RGB→HSB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@function rgb-to-hsb($baseColor) { $r-rgb: red($baseColor); $g-rgb: green($baseColor); $b-rgb: blue($baseColor); $max: max($r-rgb, $g-rgb, $b-rgb); $min: min($r-rgb, $g-rgb, $b-rgb); $h-hsb: 0; @if $max == $min { $h-hsb: 0; }@else if $max == $r-rgb { $h-hsb: 60 * (($g-rgb - $b-rgb) / ($max - $min)); } @else if $max == $g-rgb { $h-hsb: 60 * (($b-rgb - $r-rgb) / ($max - $min)) + 120; } @else if $max == $b-rgb { $h-hsb: 60 * (($r-rgb - $g-rgb) / ($max - $min)) + 240; } $h-hsb: if($h-hsb < 0, $h-hsb + 360, $h-hsb); $s-hsb: (($max - $min) / $max) * 100; $b-hsb: ($max / 255) * 100; @return $h-hsb, $s-hsb, $b-hsb; } |
HSB→RGB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
@function hsb-to-rgb($h-hsb, $s-hsb, $b-hsb) { $max: $b-hsb * 255 / 100; $min: $max - (($s-hsb / 100) * $max); $r-rgb: 0; $g-rgb: 0; $b-rgb: 0; @if 0 <= $h-hsb and $h-hsb <= 60 { $r-rgb: $max; $g-rgb: ($h-hsb / 60) * ($max - $min) + $min; $b-rgb: $min; } @else if 61 <= $h-hsb and $h-hsb <= 120 { $r-rgb: ((120 - $h-hsb) / 60) * ($max - $min) + $min; $g-rgb: $max; $b-rgb: $min; } @else if 121 <= $h-hsb and $h-hsb <= 180 { $r-rgb: $min; $g-rgb: $max; $b-rgb: (($h-hsb - 120) / 60) * ($max - $min) + $min; } @else if 181 <= $h-hsb and $h-hsb <= 240 { $r-rgb: $min; $g-rgb: ((240 - $h-hsb) / 60) * ($max - $min) + $min; $b-rgb: $max; } @else if 241 <= $h-hsb and $h-hsb <= 300 { $r-rgb: (($h-hsb - 240) / 60) * ($max - $min) + $min; $g-rgb: $min; $b-rgb: $max; } @else if 301 <= $h-hsb and $h-hsb <= 360 { $r-rgb: $max; $g-rgb: $min; $b-rgb: ((360 - $h-hsb) / 60) * ($max - $min) + $min; } @return rgb($r-rgb, $g-rgb, $b-rgb); } |
これだけだとどうにもならないので、明度を変更する関数を作ります。
1 2 3 4 |
@function calc-color-bright($baseColor, $num) { $hsb: rgb-to-hsb($baseColor); @return hsb-to-rgb(nth($hsb, 1), nth($hsb, 2), nth($hsb, 3) + $num); } |
実際に使う際には
1 |
background: calc-color-bright(#9673FF, -25) |
とすると、ベース色(#9673FF)から明度を−25した色が返ってきます。
計算上小数点が発生しますが特に丸めず、ブラウザの解釈に任せています。
同じように、色相・彩度を変更する関数も作れます。
1 2 3 4 5 6 7 8 9 10 11 |
// 色相(H値)変更 @function calc-color-hue($baseColor, $num) { $hsb: rgb-to-hsb($baseColor); @return hsb-to-rgb(nth($hsb, 1) + $num, nth($hsb, 2), nth($hsb, 3)); } // 彩度(S値)変更 @function calc-color-saturation($baseColor, $num) { $hsb: rgb-to-hsb($baseColor); @return hsb-to-rgb(nth($hsb, 1), nth($hsb, 2) + $num, nth($hsb, 3)); } |
まとめ
一部グラフィックツールではHSLが使用できるものもあるようですが、
使っているツールが対応していない場合はこういった関数を利用するのもよいかと思います。
HSLはグラデーションを作るときなどに便利なので、上手に使い分けができるといよいですね٩(๑❛ᴗ❛๑)۶
それでは今日はこのへんで!