# Function Units: Draft 1.1 *([Issue](https://github.com/sass/sass/issues/3374), [Changelog](function-units.changes.md))* This proposal restricts the use of invalid units in built-in Sass functions. ## Table of Contents * [Background](#background) * [Summary](#summary) * [Design Decisions](#design-decisions) * [Alpha Units](#alpha-units) * [Functions](#functions) * [`color.adjust()`](#coloradjust) * [`color.change()`](#colorchange) * [`color.mix()`](#colormix) * [`list.nth()` and `list.set-nth()`](#listnth-and-listset-nth) * [Deprecation Process](#deprecation-process) * [`color.adjust()`](#coloradjust-1) * [`color.change()`](#colorchange-1) * [`color.mix()`](#colormix-1) * [`list.nth()` and `list.set-nth()`](#listnth-and-listset-nth-1) ## 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. [percentages in alpha values]: https://www.w3.org/TR/css-color-4/#typedef-alpha-value ## Summary > This section is non-normative. This proposal adds the following restrictions: * The `$alpha` parameter to `color.adjust()`, `color.change()`, `opacify()`, `fade-in()`, `transparentize()`, and `fade-out()` may be either unitless or use the `%` unit. If it uses `%`, it's divided by `100%` before using it. * The `$weight` parameter to `color.mix()` must have unit `%`. * The `$n` parameter to `list.nth()` and `list.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. [Colors Level 4]: https://www.w3.org/TR/css-color-4/#typedef-alpha-value 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()`, and `fade-out()` don't need to > be modified explicitly because they're defined as calling `color.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 to `math.div($alpha, 100%)`. * If `$alpha` isn't a number between -1 and 1 (inclusive), throw an error. * Set `alpha` to `alpha + $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, let `alpha` 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 to `math.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, let `alpha` 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.