16 KiB
HWB Color Functions: Draft 1
(Issue)
This proposal adds a new hwb()
color format to the sass:color
module, along
with inspection and adjustment options for whiteness and blackness.
Table of Contents
Background
This section is non-normative.
The CSS Color Module level 4 provides several new CSS formats for
describing color, but hwb()
stands out as part of the same sRGB
color
system that Sass already uses internally.
Summary
This section is non-normative.
This proposal defines a Sassified version of the hwb()
color function
added to CSS Color Level 4 – along with relevant inspection and
adjustment options. This function will only be available inside the sass:color
module to avoid conflicts with the CSS syntax, and will be converted to more
common color-name, hex, or rgba()
syntax for output -- following the same
logic as our current color functions.
- New
color.hwb()
function describes colors in the sRGB colorspace using$hue
(defined identically to thehsl()
"hue" value), along with$whiteness
,$blackness
, and optional$alpha
transparency. - New
color.whiteness()
andcolor.blackness()
functions return the respective values ofw
orb
for a given color. - Existing
color.adjust()
,color.scale()
, andcolor.change()
functions will accept additional$whiteness
and$blackness
parameters before the final$alpha
parameter.
Design Decisions
Both rgb/a()
and hsl/a()
are available in the global namespace because both
of these formats are part of a stable CSS spec, and we want to make any standard
CSS representation of a color parse as a Sass color. However, although hwb()
is defined in Color Level 4, it's not yet implemented by any browser. Sass
policy is to avoid supporting any new CSS syntax until it's shipped in a real
browser, so hwb()
will not be available in the global namespace initially.
Instead, it will appear in the sass:color
namespace which is guaranteed to be
forwards-compatible with future CSS changes.
Because the color.hwb()
function isn't currently intended to directly
implement CSS's native hwb()
function, it will not accept special number
string or special variable string values that can only be resolved in CSS.
However, for consistency with Sass's rgb()
and hsl()
functions it will
support both space-delimited and comma-delimited arguments.
Future Designs
It's likely that as CSS Color Level 4 matures, hwb()
will be stabilized and
supported in browsers in one form or another. At this point, Sass will likely
add support for a global hwb()
function that's compatible with its CSS usage,
including supporting special number and variable strings. The details of this
are left to a future proposal.
Procedures
Scaling a Number
This algorithm takes a number number
, a value factor
, and a number max
.
It's written "scale <number>
by <factor>
with a max
of <max>
". It
returns a number with a value between 0 and max
and the same units as
number
.
Note: in practice, this is only ever called with
number <= max
.
-
If
factor
isn't a number with unit%
between-100%
and100%
(inclusive), throw an error. -
If
factor > 0%
, returnnumber + (max - number) * factor / 100%
. -
Otherwise, return
number + number * factor / 100%
.
Functions
All new functions are part of the sass:color
built-in module.
hwb()
-
hwb($hue, $whiteness, $blackness, $alpha: 1)
-
If any of
$hue
,$whiteness
,$blackness
, or$alpha
aren't numbers, throw an error. -
If
$hue
has any units other thandeg
, throw an error. -
If either of
$whiteness
or$blackness
don't have unit%
or aren't between0%
and100%
(inclusive), throw an error. -
Let
hue
be$hue
without units. -
Let
whiteness
be$whiteness / 100%
. -
Let
blackness
be$blackness / 100%
. -
If
whiteness + blackness > 1
:-
Set
whiteness
towhiteness / (whiteness + blackness)
. -
Set
blackness
toblackness / (whiteness + blackness)
.
-
-
Let
red
,green
, andblue
be the result of convertinghue
,whiteness
, andblackness
to RGB. -
Set
red
,green
, andblue
to their existing values multiplied by 255 and rounded to the nearest integers. -
Let
alpha
be the result of percent-converting$alpha
with amax
of 1. -
Return a color with the given
red
,green
,blue
, andalpha
channels.
-
-
hwb($channels)
-
If
$channels
is not an unbracketed space-separated list, throw an error. -
If
$channels
does not includes exactly three elements, throw an error. -
Let
hue
andwhiteness
be the first two elements of$channels
-
If the third element of
$channels
has preserved its status as two slash-separated numbers:- Let
blackness
be the number before the slash andalpha
the number after the slash.
- Let
-
Otherwise:
- Let
blackness
be the third element of$channels
.
- Let
-
Call
hwb()
withhue
,whiteness
,blackness
, andalpha
(if it's defined) as arguments and return the result.
-
whiteness()
whiteness($color)
-
If
$color
is not a color, throw an error. -
Return a number with unit
%
between0%
and100%
(inclusive) such that:-
hwb(hue($color), whiteness($color), blackness($color))
returns a color with the same red, green, and blue channels as$color
. -
whiteness($color) + blackness($color) <= 100%
.
The specific number returned here is left purposefully open-ended to allow implementations to pursue different strategies for representing color values. For example, one implementation may eagerly convert all colors to RGB channels and convert back when
whiteness()
orblackness()
is called, where another may keep around their original HWB values and return those as-is. -
blackness()
blackness($color)
-
If
$color
is not a color, throw an error. -
Return a number with unit
%
between0%
and100%
(inclusive) such that:-
hwb(hue($color), whiteness($color), blackness($color))
returns a color with the same red, green, and blue channels as$color
. -
whiteness($color) + blackness($color) <= 100%
.
The specific number returned here is left purposefully open-ended to allow implementations to pursue different strategies for representing color values. For example, one implementation may eagerly convert all colors to RGB channels and convert back when
whiteness()
orblackness()
is called, where another may keep around their original HWB values and return those as-is. -
adjust()
This proposal adds new $whiteness
and $blackness
parameters to the adjust()
function, and its global adjust-color()
alias.
adjust($color,
$red: null, $green: null, $blue: null,
$hue: null, $saturation: null, $lightness: null,
$whiteness: null, $blackness: null,
$alpha: null)
This function's new definition is as follows:
-
If
$color
isn't a color, throw an error. -
Let
alpha
be$color
's alpha channel. -
If
$alpha
isn't null:-
If
$alpha
isn't a number between -1 and 1 (inclusive), throw an error. -
Set
alpha
toalpha + $alpha
clamped between 0 and 1.
-
-
If
$hue
isn't a number or null, throw an error. -
If any of
$red
,$green
, or$blue
aren't null:-
If any of
$hue
,$saturation
,$lightness
,$whiteness
, or$blackness
aren't null, throw an error. -
If any of
$red
,$green
, or$blue
aren't either null or numbers between -255 and 255 (inclusive), throw an error. -
Let
red
,green
, andblue
be$color
's red, green, and blue channels. -
If
$red
isn't null, setred
tored + $red
clamped between 0 and 255. -
If
$green
isn't null, setgreen
togreen + $green
clamped between 0 and 255. -
If
$blue
isn't null, setblue
toblue + $blue
clamped between 0 and 255. -
Return a color with
red
,green
,blue
, andalpha
as the red, green, blue, and alpha channels, respectively.
-
-
Otherwise, if either
$saturation
or$lightness
aren't null:-
If either
$whiteness
or$blackness
aren't null, throw an error. -
If either
$saturation
or$lightness
aren't either null or numbers between -100 and 100 (inclusive), throw an error. -
Let
hue
,saturation
, andlightness
be the result of callinghue($color)
,saturation($color)
, andlightness($color)
respectively. -
If
$hue
isn't null, sethue
tohue + $hue
. -
If
$saturation
isn't null, setsaturation
tosaturation + $saturation
clamped between 0 and 100. -
If
$lightness
isn't null, setlightness
tolightness + $lightness
clamped between 0 and 100. -
Return the result of calling
hsl()
withhue
,saturation
,lightness
, andalpha
.
-
-
Otherwise, if either
$hue
,$whiteness
, or$blackness
aren't null:-
If either
$whiteness
or$blackness
aren't either null or numbers with unit%
between-100%
and100%
(inclusive), throw an error. -
Let
hue
,whiteness
, andblackness
be the result of callinghue($color)
,whiteness($color)
, andblackness($color)
respectively. -
If
$hue
isn't null, sethue
tohue + $hue
. -
If
$whiteness
isn't null, setwhiteness
towhiteness + $whiteness
clamped between0%
and100%
. -
If
$blackness
isn't null, setblackness
toblackness + $blackness
clamped between0%
and100%
. -
Return the result of calling
hwb()
withhue
,whiteness
,blackness
, andalpha
.
-
-
Otherwise, return a color with the same red, green, and blue channels as
$color
andalpha
as its alpha channel.
change()
This proposal adds new $whiteness
and $blackness
parameters to the change()
function, and its global change-color()
alias.
change($color,
$red: null, $green: null, $blue: null,
$hue: null, $saturation: null, $lightness: null,
$whiteness: null, $blackness: null,
$alpha: null)
This function's new definition is as follows:
-
If
$color
isn't a color, throw an error. -
If
$alpha
isn't either null or a number between 0 and 1 (inclusive), throw an error. -
Let
alpha
be$color
's alpha channel if$alpha
is null or$alpha
without units otherwise. -
If
$hue
isn't a number or null, throw an error. -
If any of
$red
,$green
, or$blue
aren't null:-
If any of
$hue
,$saturation
,$lightness
,$whiteness
, or$blackness
aren't null, throw an error. -
If any of
$red
,$green
, or$blue
aren't either null or numbers between 0 and 255 (inclusive), throw an error. -
Let
red
be$color
's red channel if$red
is null or$red
without units otherwise. -
Let
green
be$color
's green channel if$green
is null or$green
without units otherwise. -
Let
blue
be$color
's blue channel if$blue
is null or$blue
without units otherwise. -
Return a color with
red
,green
,blue
, andalpha
as the red, green, blue, and alpha channels, respectively.
-
-
Otherwise, if either
$saturation
or$lightness
aren't null:-
If either
$whiteness
or$blackness
aren't null, throw an error. -
If either
$saturation
or$lightness
aren't either null or numbers between 0 and 100 (inclusive), throw an error. -
Let
hue
be the result of callinghue($color)
if$hue
is null, or$hue
otherwise. -
Let
saturation
be the result of callingsaturation($color)
if$saturation
is null, or$saturation
otherwise. -
Let
lightness
be the result of callinglightness($color)
if$lightness
is null, or$lightness
otherwise. -
Return the result of calling
hsl()
withhue
,saturation
,lightness
, andalpha
.
-
-
Otherwise, if either
$hue
,$whiteness
, or$blackness
aren't null:-
If either
$whiteness
or$blackness
aren't either null or numbers with unit%
between0%
and100%
(inclusive), throw an error. -
Let
hue
be the result of callinghue($color)
if$hue
is null, or$hue
otherwise. -
Let
whiteness
be the result of callingwhiteness($color)
if$whiteness
is null, or$whiteness
otherwise. -
Let
blackness
be the result of callingblackness($color)
if$blackness
is null, or$blackness
otherwise. -
Return the result of calling
hwb()
withhue
,whiteness
,blackness
, andalpha
.
-
-
Otherwise, return a color with the same red, green, and blue channels as
$color
andalpha
as its alpha channel.
scale()
This proposal adds new $whiteness
and $blackness
parameters to the scale()
function, and its global scale-color()
alias.
scale($color,
$red: null, $green: null, $blue: null,
$saturation: null, $lightness: null,
$whiteness: null, $blackness: null,
$alpha: null)
This function's new definition is as follows:
-
If
$color
isn't a color, throw an error. -
Let
alpha
be$color
's alpha channel. -
If
$alpha
isn't null, setalpha
to the result of scalingalpha
by$alpha
withmax
1. -
If any of
$red
,$green
, or$blue
aren't null:-
If any of
$saturation
,$lightness
,$whiteness
, or$blackness
aren't null, throw an error. -
Let
red
,green
, andblue
be$color
's red, green, and blue channels. -
If
$red
isn't null, setred
to the result of scalingred
by$red
withmax
255. -
If
$green
isn't null, setgreen
to the result of scalinggreen
by$green
withmax
255. -
If
$blue
isn't null, setblue
to the result of scalingblue
by$blue
withmax
255. -
Return a color with
red
,green
,blue
, andalpha
as the red, green, blue, and alpha channels, respectively.
-
-
Otherwise, if either
$saturation
or$lightness
aren't null:-
If either
$whiteness
or$blackness
aren't null, throw an error. -
Let
hue
,saturation
, andlightness
be the result of callinghue($color)
,saturation($color)
, andlightness($color)
respectively. -
If
$saturation
isn't null, setsaturation
to the result of scalingsaturation
by$saturation
withmax
100%
. -
If
$lightness
isn't null, setlightness
to the result of scalinglightness
by$lightness
withmax
100%
. -
Return the result of calling
hsl()
withhue
,saturation
,lightness
, andalpha
.
-
-
Otherwise, if either
$hue
,$whiteness
, or$blackness
aren't null:-
Let
hue
,whiteness
, andblackness
be the result of callinghue($color)
,whiteness($color)
, andblackness($color)
respectively. -
If
$whiteness
isn't null, setwhiteness
to the result of scalingwhiteness
by$whiteness
withmax
100%
. -
If
$blackness
isn't null, setblackness
to the result of scalingblackness
by$blackness
withmax
100%
. -
Return the result of calling
hwb()
withhue
,whiteness
,blackness
, andalpha
.
-
-
Otherwise, return a color with the same red, green, and blue channels as
$color
andalpha
as its alpha channel.