sass/accepted/color-4-rgb-hsl.md
Natalie Weizenbaum 9f0cb1fb43 Fix broken link references
This also moves a bunch of references around to work around
markedjs/marked#1566.
2019-11-26 20:32:39 -08:00

221 lines
7.3 KiB
Markdown

# Color Level 4 `rgb()` and `hsl()` Functions: Draft 1.3
*([Issue](https://github.com/sass/sass/issues/2564), [Changelog](color-4-rgb-hsl.changes.md))*
This proposal expands Sass's built-in `rgb()`, `rgba()`, `hsl()`, and `hsla()`
functions to support the new terse syntax defined in [CSS Color Level 4][].
[CSS Color Level 4]: https://drafts.csswg.org/css-color/
## Table of Contents
* [Summary](#summary)
* [Definitions](#definitions)
* [Special Number String](#special-number-string)
* [Special Variable String](#special-variable-string)
* [Semantics](#semantics)
## Summary
> This section is non-normative.
Sass's `rgb()` and `hsl()` functions will add support for the Color Level 4
syntax, so `rgb(179 115 153)`, `rgb(70% 45% 60%)`, and `hsl(324deg 29% 57%)`
will all return the same color. They'll also support the slash-separated alpha
syntax using [the normal rules][] for distinguishing between division and `/`,
so `rgb(179 115 153 / 50%)` will return a 50%-opacity color but
`rgb(179 115 $blue / 50%)` will not.
[the normal rules]: https://sass-lang.com/documentation/file.SASS_REFERENCE.html#division-and-slash
Color Level 4 redefines `rgba()` and `hsla()` as pure aliases for `rgb()` and
`hsl()`, which also means that `rgb()` and `hsl()` support the old syntax for
defining colors with alpha channels. In keeping with this, Sass will redefine
`rgba()` and `hsla()` as aliases for `rgb()` and `hsl()` as well, and add
support to the latter for the former's syntax. This includes the Sass-specific
`rgba($color, $alpha)` syntax, which will now work with `rgb()` and `hsl()` as
well.
Sass will continue generating colors with alpha channels as `rgba()` calls, for
backwards-compatibility with older browsers that don't yet support Color Level
4.
## Definitions
### Special Number String
A *special number string* is an unquoted string that CSS will recognize as a
function that may return a number. For the purposes of Sass, this is any
unquoted string that begins with `calc(` or `var(`. This matching is
case-insensitive.
> Sass functions that shadow CSS functions must work with any invocation that
> CSS allows, which includes allowing special number strings anywhere a number
> would be allowed.
>
> This is intended to match the existing behavior for determining special number
> strings for `rgb()`, `hsl()`, `rgba()`, and `hsla()`.
### Special Variable String
A *special variable string* is [special number string][] that begins with
`var(`. This matching is case-insensitive.
[special number string]: #special-number-string
> Unlike other special number strings, variables can expand into multiple
> arguments to a single function.
>
> This is intended to match the existing behavior for determining special
> variable strings for `rgb()`, `hsl()`, `rgba()`, and `hsla()`.
## Semantics
This proposal adds new overloads to the `rgb()`, `hsl()`, `rgba()`, and `hsla()`
functions:
* ```
rgb($channels)
```
* If `$channels` is a [special variable string][], return a plain CSS function
string with the name `"rgb"` and the argument `$channels`.
* If `$channels` is not an unbracketed space-separated list, throw an error.
* If `$channels` has more than three elements, throw an error.
* If `$channels` has fewer than three elements:
* If any element of `$channels` is a [special variable string][], return a
plain CSS function string with the name `"rgb"` and the argument
`$channels`.
* If the last element of `$channels` is an unquoted string that begins with
`var(` and contains `/`, return a plain CSS function string with the name
`"rgb"` and the argument `$channels`.
* Otherwise, throw an error.
* Let `red` and `green` be the first two elements of `$channels`.
* If the third element of `$channels` is an unquoted string that contains `/`:
* Return a plain CSS function string with the name `"rgb"` and the argument
`$channels`.
* Otherwise, if the third element of `$channels` has preserved its status as
two slash-separated numbers:
* Let `blue` be the number before the slash and `alpha` the number after the
slash.
* Otherwise:
* Let `blue` be the third element of `$channels`.
* Call `rgb()` with `red`, `green`, `blue`, and `alpha` (if it's defined) as
arguments and return the result.
[special variable string]: #special-variable-string
* ```
rgb($red, $green, $blue, $alpha)
```
* Call `rgba()` with the same argument and return the result, except that if
it would return a plain CSS function named `"rgb"` that function is named
`"rgba"` instead.
* ```
rgb($color, $alpha)
```
* If either argument is a [special variable string][], return a plain CSS
function string with the name `"rgb"` and the same arguments.
* Call `rgba()` with the same arguments and return the result.
* ```
hsl($channels)
```
* If `$channels` is a [special variable string][], return a plain CSS function
string with the name `"hsl"` and the argument `$channels`.
* If `$channels` is not an unbracketed space-separated list, throw an error.
* If `$channels` has more than three elements, throw an error.
* If `$channels` has fewer than three elements:
* If any element of `$channels` is a [special variable string][], return a
plain CSS function string with the name `"hsl"` and the argument
`$channels`.
* If the last element of `$channels` is an unquoted string that begins with
`var(` and contains `/`, return a plain CSS function string with the name
`"hsl"` and the argument `$channels`.
* Otherwise, throw an error.
* Let `hue` and `saturation` be the first two elements of `$channels`.
* If the third element of `$channels` is an unquoted string that contains `/`:
* Return a plain CSS function string with the name `"rgb"` and the argument
`$channels`.
* Otherwise, if the third element of `$channels` has preserved its status as
two slash-separated numbers:
* Let `lightness` be the number before the slash and `alpha` the number
after the slash.
* Otherwise:
* Let `lightness` be the third element of `$channels`.
* Call `hsl()` with `hue`, `saturation`, `lightness`, and `alpha` (if it's
defined) as arguments and return the result.
* ```
hsl($hue, $saturation, $lightness, $alpha)
```
* Call `hsla()` with the same arguments and return the result, except that if
it would return a plain CSS function named `"hsla"` that function is named
`"hsl"` instead.
* ```
rgba($channels)
```
* Call `rgb()` with the same argument and return the result, except that if
it would return a plain CSS function named `"rgb"` that function is named
`"rgba"` instead.
* ```
rgba($red, $green, $blue)
```
* Call `rgb()` with the same argument and return the result, except that if
it would return a plain CSS function named `"rgb"` that function is named
`"rgba"` instead.
* ```
hsla($channels)
```
* Call `hsl()` with the same arguments and return the result, except that if
it would return a plain CSS function named `"hsl"` that function is named
`"hsla"` instead.
* ```
hsla($hue, $saturation, $lightness)
```
* Call `hsl()` with the same arguments and return the result, except that if
it would return a plain CSS function named `"hsl"` that function is named
`"hsla"` instead.