5.4 KiB
Function Units: Draft 1.1
This proposal restricts the use of invalid units in built-in Sass functions.
Table of Contents
Background
This section is non-normative.
Sass functions added early during Sass's lifetime were generally quite
permissive, allowing numbers with units to be passed even if the units were
ignored. However, this is often quite confusing in practice; for example, a user
might expect that color.adjust($color, $alpha: -1%)
would return a color with
0.01
less alpha. In fact it returns a transparent color, because the unit is
ignored entirely.
In some cases, CSS has even added support for units to functions after the fact—including support for percentages in alpha values. In that case, Sass has been forced to deprecate passing incorrect units to those functions before adding support for new units.
Summary
This section is non-normative.
This proposal adds the following restrictions:
-
The
$alpha
parameter tocolor.adjust()
,color.change()
,opacify()
,fade-in()
,transparentize()
, andfade-out()
may be either unitless or use the%
unit. If it uses%
, it's divided by100%
before using it. -
The
$weight
parameter tocolor.mix()
must have unit%
. -
The
$n
parameter tolist.nth()
andlist.set-nth()
may not have units.
Design Decisions
Alpha Units
One alternative would be to forbid units in $alpha
parameters entirely, as
we're doing for $n
parameters. However, since Colors Level 4 supports
percentage-style alphas (as do Sass's hsl()
, rgb()
, and hwb()
functions),
it's much more friendly and consistent to allow them.
There is some risk that users are already passing %
units to alpha values and
will have their colors change unexpectedly. However, deprecation warnings should
alert these users in time to change their code, and even if they miss the
warnings it's likely they expected the new behavior in the first place so in a
sense the change will be a bug fix for them.
Functions
opacify()
,fade-in()
,transparentize()
, andfade-out()
don't need to be modified explicitly because they're defined as callingcolor.adjust()
internally.
color.adjust()
Replace the "If $alpha
isn't null" block with the following:
-
If
$alpha
isn't null:-
If
$alpha
isn't a number, throw an error. -
If
$alpha
has units other than%
, throw an error. -
If
$alpha
has unit%
, set it tomath.div($alpha, 100%)
. -
If
$alpha
isn't a number between -1 and 1 (inclusive), throw an error. -
Set
alpha
toalpha + $alpha
clamped between 0 and 1.
-
color.change()
Replace
-
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.
with
-
If
$alpha
is null, letalpha
be$color
's alpha channel. Otherwise:-
If
$alpha
isn't a number, throw an error. -
If
$alpha
has units other than%
, throw an error. -
If
$alpha
has unit%
, set it tomath.div($alpha, 100%)
. -
If
$alpha
isn't a number between 0 and 1 (inclusive), throw an error. -
Let
alpha
be$alpha
.
-
color.mix()
Add the following to the beginning of the function's definition:
- If
$weight
isn't a number with unit%
, throw an error.
list.nth()
and list.set-nth()
Add the following to the beginning of these functions' definitions:
- If
$n
isn't a unitless integer, throw an error.
Deprecation Process
Before an implementation releases its next major version, it should make the following changes instead of those listed above:
color.adjust()
Add the following to the beginning of the "If $alpha
isn't null" block:
- If
$alpha
has any units, emit a deprecation warning.
color.change()
Replace
-
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.
with
-
If
$alpha
is null, letalpha
be$color
's alpha channel. Otherwise:-
If
$alpha
isn't a number, throw an error. -
If
$alpha
has any units, emit a deprecation warning. -
If
$alpha
isn't a number between 0 and 1 (inclusive), throw an error. -
Let
alpha
be$alpha
.
-
color.mix()
Add the following to the beginning of the function's definition:
- If
$weight
is a unitless number or a number with units other than%
, emit a deprecation warning.
list.nth()
and list.set-nth()
Add the following to the beginning of these functions' definitions:
- If
$n
is a number with units, emit a deprecation warning.