diff --git a/source/assets/sass/visual-design/_theme.scss b/source/assets/sass/visual-design/_theme.scss index 108ac2b5e..48f893fcc 100644 --- a/source/assets/sass/visual-design/_theme.scss +++ b/source/assets/sass/visual-design/_theme.scss @@ -32,10 +32,6 @@ body { color: var(--text, var(--sl-color--pale-sky)); } -.fade { - opacity: 0.7; -} - ::selection { background: var(--sl-color--iron); } diff --git a/source/documentation/modules/color.md b/source/documentation/modules/color.md index 28a666079..29c7a6f8b 100644 --- a/source/documentation/modules/color.md +++ b/source/documentation/modules/color.md @@ -9,657 +9,60 @@ title: sass:color $red: null, $green: null, $blue: null, $hue: null, $saturation: null, $lightness: null, $whiteness: null, $blackness: null, - $x: null, $y: null, $z: null, - $chroma: null, - $alpha: null, - $space: null) + $alpha: null) {% endcapture %} {% function color_adjust, 'adjust-color(...)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$x, $y, $z, $chroma, and $space"' %}{% endcompatibility %} {% compatibility 'dart: "1.28.0"', 'libsass: false', 'ruby: false', 'feature: "$whiteness and $blackness"' %}{% endcompatibility %} - Increases or decreases one or more channels of `$color` by fixed amounts. + Increases or decreases one or more properties of `$color` by fixed amounts. - Adds the value passed for each keyword argument to the corresponding channel - of the color, and returns the adjusted color. By default, this can only adjust - channels in `$color`'s space, but a different color space can be passed as - `$space` to adjust channels there instead. This always returns a color in the - same space as `$color`. + Adds the value passed for each keyword argument to the corresponding property + of the color, and returns the adjusted color. It's an error to specify an RGB + property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL + property (`$hue`, `$saturation`, and/or `$lightness`), or either of those at + the same time as an [HWB][] property (`$hue`, `$whiteness`, and/or + `$blackness`). - {% headsUp %} - For historical reasons, if `$color` is in a [legacy color space], _any_ - legacy color space channels can be adjusted. However, it's an error to - specify an RGB channel (`$red`, `$green`, and/or `$blue`) at the same time - as an HSL channel (`$hue`, `$saturation`, and/or `$lightness`), or either of - those at the same time as an [HWB] channel (`$hue`, `$whiteness`, and/or - `$blackness`). - - [legacy color space]: /documentation/values/colors#legacy-color-spaces - [HWB]: https://en.wikipedia.org/wiki/HWB_color_model + [HWB]: https://en.wikipedia.org/wiki/HWB_color_model - Even so, it's a good idea to pass `$space` explicitly even for legacy colors. - {% endheadsUp %} + All optional arguments must be numbers. The `$red`, `$green`, and `$blue` + arguments must be [unitless][] and between -255 and 255 (inclusive). The + `$hue` argument must have either the unit `deg` or no unit. The `$saturation`, + `$lightness`, `$whiteness`, and `$blackness` arguments must be between `-100%` + and `100%` (inclusive), and may not be unitless. The `$alpha` argument must be + unitless and between -1 and 1 (inclusive). - All channel arguments must be numbers, and must be units that could be passed - for those channels in the color space's constructor. If the existing channel - value plus the adjustment value is outside the channel's native range, it's - clamped for: - - * red, green, and blue channels for the `rgb` space; - * lightness channel for the `lab`, `lch`, `oklab`, and `oklch` spaces; - * the lower bound of the saturation and chroma channels for the `hsl`, `lch`, - and `oklch` spaces; - * and the alpha channel for all spaces. + [unitless]: /documentation/values/numbers#units See also: * [`color.scale()`](#scale) for fluidly scaling a color's properties. * [`color.change()`](#change) for setting a color's properties. - {% codeExample 'adjust-color', false %} + {% codeExample 'adjust-color' %} @use 'sass:color'; @debug color.adjust(#6b717f, $red: 15); // #7a717f - @debug color.adjust(lab(40% 30 40), $lightness: 10%, $a: -20); // lab(50% 10 40) - @debug color.adjust(#d2e1dd, $hue: 45deg, $space: oklch); - // rgb(209.7987626149, 223.8632000471, 229.3988769575) + @debug color.adjust(#d2e1dd, $red: -10, $blue: 10); // #c8e1e7 + @debug color.adjust(#998099, $lightness: -30%, $alpha: -0.4); // rgba(71, 57, 71, 0.6) === @use 'sass:color' @debug color.adjust(#6b717f, $red: 15) // #7a717f - @debug color.adjust(lab(40% 30 40), $lightness: 10%, $a: -20) // lab(50% 10 40) - @debug color.adjust(#d2e1dd, $hue: 45deg, $space: oklch) - // rgb(209.7987626149, 223.8632000471, 229.3988769575) - {% endcodeExample %} -{% endfunction %} - -{% capture color_change %} - color.change($color, - $red: null, $green: null, $blue: null, - $hue: null, $saturation: null, $lightness: null, - $whiteness: null, $blackness: null, - $x: null, $y: null, $z: null, - $chroma: null, - $alpha: null, - $space: null) -{% endcapture %} - -{% function color_change, 'change-color(...)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$x, $y, $z, $chroma, and $space"' %}{% endcompatibility %} - {% compatibility 'dart: "1.28.0"', 'libsass: false', 'ruby: false', 'feature: "$whiteness and $blackness"' %}{% endcompatibility %} - - Sets one or more channels of a color to new values. - - Uses the value passed for each keyword argument in place of the corresponding - color channel, and returns the changed color. By default, this can only change - channels in `$color`'s space, but a different color space can be passed as - `$space` to adjust channels there instead. This always returns a color in the - same space as `$color`. - - {% headsUp %} - - For historical reasons, if `$color` is in a [legacy color space], _any_ - legacy color space channels can be changed. However, it's an error to - specify an RGB channel (`$red`, `$green`, and/or `$blue`) at the same time - as an HSL channel (`$hue`, `$saturation`, and/or `$lightness`), or either - of those at the same time as an [HWB] channel (`$hue`, `$whiteness`, and/or - `$blackness`). - - [legacy color space]: /documentation/values/colors#legacy-color-spaces - [HWB]: https://en.wikipedia.org/wiki/HWB_color_model - - Even so, it's a good idea to pass `$space` explicitly even for legacy colors. - {% endheadsUp %} - - All channel arguments must be numbers, and must be units that could be passed - for those channels in the color space's constructor. Channels are never - clamped for `color.change()`. - - See also: - - * [`color.scale()`](#scale) for fluidly scaling a color's properties. - * [`color.adjust()`](#adjust) for adjusting a color's properties by fixed - amounts. - - {% codeExample 'color-change', false %} - @use 'sass:color'; - - @debug color.change(#6b717f, $red: 100); // #64717f - @debug color.change(color(srgb 0 0.2 0.4), $red: 0.8, $blue: 0.1); - // color(srgb 0.8 0.1 0.4) - @debug color.change(#998099, $lightness: 30%, $space: oklch); - // rgb(58.0719961509, 37.2631531594, 58.4201613409) - === - @use 'sass:color' - - @debug color.change(#6b717f, $red: 100) // #64717f - @debug color.change(color(srgb 0 0.2 0.4), $red: 0.8, $blue: 0.1) - // color(srgb 0.8 0.1 0.4) - @debug color.change(#998099, $lightness: 30%, $space: oklch) - // rgb(58.0719961509, 37.2631531594, 58.4201613409) - {% endcodeExample %} -{% endfunction %} - -{% function 'color.complement($color, $space: null)', 'complement($color, $space: null)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$space"' %}{% endcompatibility %} - - Returns the [complement] of `$color` in `$space`. - - [complement]: https://en.wikipedia.org/wiki/Complementary_colors - - This rotates `$color`'s hue by `180deg` in `$space`. This means that `$space` - has to be a polar color space: `hsl`, `hwb`, `lch`, or `oklch`. It always - returns a color in the same space as `$color`. - - {% headsUp %} - For historical reasons, `$space` is optional if `$color` is in a [legacy - color space]. In that case, `$space` defaults to `hsl`. It's always a good - idea to pass `$space` explicitly regardless. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces - {% endheadsUp %} - - {% codeExample 'color-complement', false %} - @use 'sass:color'; - - // HSL hue 222deg becomes 42deg. - @debug color.complement(#6b717f); // #7f796b - - // Oklch hue 267.1262408996deg becomes 87.1262408996deg - @debug color.complement(#6b717f, oklch); - // rgb(118.8110604298, 112.5123650034, 98.1616586336) - - // Hue 70deg becomes 250deg. - @debug color.complement(oklch(50% 0.12 70deg), oklch); // oklch(50% 0.12 250deg) - === - @use 'sass:color' - - // HSL hue 222deg becomes 42deg. - @debug color.complement(#6b717f) // #7f796b - - // Oklch hue 267.1262408996deg becomes 87.1262408996deg - @debug color.complement(#6b717f, oklch) - // rgb(118.8110604298, 112.5123650034, 98.1616586336) - - // Hue 70deg becomes 250deg. - @debug color.complement(oklch(50% 0.12 70deg), oklch) // oklch(50% 0.12 250deg) - {% endcodeExample %} -{% endfunction %} - -{% function 'color.channel($color, $channel, $space: null)', 'returns:number' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$space"' %}{% endcompatibility %} - - Returns the value of `$channel` in `$space`, which defaults to `$color`'s - space. The `$channel` must be a quoted string, and the `$space` must be an - unquoted string. - - This returns a number with unit `deg` for the `hue` channel of the `hsl`, - `hwb`, `lch`, and `oklch` spaces. It returns a number with unit `%` for the - `saturation`, `lightness`, `whiteness`, and `blackness` channels of the `hsl`, - `hwb`, `lab`, `lch`, `oklab`, and `oklch` spaces. For all other channels, it - returns a unitless number. - - This will return `0` (possibly with an appropriate unit) if the `$channel` is - missing in `$color`. You can use [`color.is-missing()`] to check explicitly - for missing channels. - - [`color.is-missing()`]: #is-missing - - {% codeExample 'color-channel', false %} - @use 'sass:color'; - - @debug color.channel(hsl(80deg 30% 50%), "hue"); // 80deg - @debug color.channel(hsl(80deg 30% 50%), "hue", $space: oklch); // 124.279238779deg - @debug color.channel(hsl(80deg 30% 50%), "red", $space: rgb); // 140.25 - === - @use 'sass:color' - - @debug color.channel(hsl(80deg 30% 50%), "hue") // 80deg - @debug color.channel(hsl(80deg 30% 50%), "hue", $space: oklch) // 124.279238779deg - @debug color.channel(hsl(80deg 30% 50%), "red", $space: rgb) // 140.25 - {% endcodeExample %} -{% endfunction %} - -{% function 'color.grayscale($color)', 'grayscale($color)', 'returns:color' %} - Returns a gray color with the same lightness as `$color`. - - If `$color` is in a [legacy color space], this sets the HSL saturation to 0%. - Otherwise, it sets the Oklch chroma to 0%. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces - - {% codeExample 'color-grayscale', false %} - @use 'sass:color'; - - @debug color.grayscale(#6b717f); // #757575 - @debug color.grayscale(color(srgb 0.4 0.2 0.6)); // color(srgb 0.3233585271 0.3233585411 0.3233585792) - @debug color.grayscale(oklch(50% 80% 270deg)); // oklch(50% 0% 270deg) - === - @use 'sass:color' - - @debug color.grayscale(#6b717f) // #757575 - @debug color.grayscale(color(srgb 0.4 0.2 0.6)) // color(srgb 0.3233585271 0.3233585411 0.3233585792) - @debug color.grayscale(oklch(50% 80% 270deg)) // oklch(50% 0% 270deg) - {% endcodeExample %} -{% endfunction %} - -{% function 'color.ie-hex-str($color)', 'ie-hex-str($color)', 'returns:unquoted string' %} - Returns an unquoted string that represents `$color` in the `#AARRGGBB` format - expected by Internet Explorer's [`-ms-filter`] property. - - [`-ms-filter`]: https://learn.microsoft.com/en-us/previous-versions/ms530752(v=vs.85) - - If `$color` isn't already in the `rgb` color space, it's converted to `rgb` - and gamut-mapped if necessary. The specific gamut-mapping algorithm may change - in future Sass versions as the state of the art improves; currently, - [`local-minde`] is used. - - [`local-minde`]: #to-gamut - - {% codeExample 'color-ie-hex-str', false %} - @use 'sass:color'; - - @debug color.ie-hex-str(#b37399); // #FFB37399 - @debug color.ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4 - @debug color.ie-hex-str(oklch(70% 10% 120deg)); // #FF9BA287 - === - @use 'sass:color' - - @debug color.ie-hex-str(#b37399) // #FFB37399 - @debug color.ie-hex-str(rgba(242, 236, 228, 0.6)) // #99F2ECE4 - @debug color.ie-hex-str(oklch(70% 10% 120deg)) // #FF9BA287 - {% endcodeExample %} -{% endfunction %} - -{% function 'color.invert($color, $weight: 100%, $space: null)', 'invert($color, $weight: 100%, $space: null)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$space"' %}{% endcompatibility %} - - Returns the inverse or [negative] of `$color` in `$space`. - - [negative]: https://en.wikipedia.org/wiki/Negative_(photography) - - The `$weight` must be a number between `0%` and `100%` (inclusive). A higher - weight means the result will be closer to the negative, and a lower weight - means it will be closer to `$color`. Weight `50%` will always produce a - medium-lightness gray in `$space`. - - {% headsUp %} - For historical reasons, `$space` is optional if `$color` is in a [legacy - color space]. In that case, `$space` defaults to `$color`'s own space. It's - always a good idea to pass `$space` explicitly regardless. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces - {% endheadsUp %} - - {% codeExample 'color-invert', false %} - @use 'sass:color'; - - @debug color.invert(#b37399, $space: rgb); // #4c8c66 - @debug color.invert(#550e0c, 20%, $space: display-p3); // rgb(103.4937692017, 61.3720912206, 59.430641338) - === - @use 'sass:color'; - - @debug color.invert(#b37399, $space: rgb) // #4c8c66 - @debug color.invert(#550e0c, 20%, $space: display-p3) // rgb(103.4937692017, 61.3720912206, 59.430641338) + @debug color.adjust(#d2e1dd, $red: -10, $blue: 10) // #c8e1e7 + @debug color.adjust(#998099, $lightness: -30%, $alpha: -0.4) // rgba(71, 57, 71, 0.6) {% endcodeExample %} {% endfunction %} -{% function 'color.is-legacy($color)', 'returns:boolean' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$space"' %}{% endcompatibility %} - -Returns whether `$color` is in a [legacy color space]. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces - - {% codeExample 'color-is-legacy', false %} - @use 'sass:color'; - - @debug color.is-legacy(#b37399); // true - @debug color.is-legacy(hsl(90deg 30% 90%)); // true - @debug color.is-legacy(oklch(70% 10% 120deg)); // false - === - @use 'sass:color' - - @debug color.is-legacy(#b37399) // true - @debug color.is-legacy(hsl(90deg 30% 90%)) // true - @debug color.is-legacy(oklch(70% 10% 120deg)) // false - {% endcodeExample %} -{% endfunction %} - -{% function 'color.is-missing($color, $channel)', 'returns:boolean' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$space"' %}{% endcompatibility %} - -Returns whether `$channel` is [missing] in `$color`. The `$channel` must be a - quoted string. - - [missing channel]: /documentation/values/colors#missing-channels - - {% codeExample 'color-is-missing', false %} - @use 'sass:color'; - - @debug color.is-missing(#b37399, "green"); // false - @debug color.is-missing(rgb(100 none 200), "green"); // true - @debug color.is-missing(color.to-space(grey, lch), "hue"); // true - === - @use 'sass:color' - - @debug color.is-legacy(#b37399) // true - @debug color.is-legacy(hsl(90deg 30% 90%)) // true - @debug color.is-legacy(oklch(70% 10% 120deg)) // false - {% endcodeExample %} -{% endfunction %} - -{% function 'color.is-powerless($color, $channel, $space: null)', 'returns:boolean' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$space"' %}{% endcompatibility %} - -Returns whether `$color`'s `$channel` is [powerless] in `$space`, which - defaults to `$color`'s space. The `$channel` must be a quoted string and the - `$space` must be an unquoted string. - - [powerless]: /documentation/values/colors#powerless-channels - - Channels are considered powerless in the following circumstances: - - * In the `hsl` space, the `hue` is powerless if the `saturation` is 0%. - * In the `hwb` space, the `hue` is powerless if the `whiteness` plus the - `blackness` is greater than 100%. - * In the `lch` and `oklch` spaces, the `hue` is powerless if the `chroma` is - 0%. - - {% codeExample 'color-is-powerless', false %} - @use 'sass:color'; - - @debug color.is-powerless(hsl(180deg 0% 40%), "hue"); // true - @debug color.is-powerless(hsl(180deg 0% 40%), "saturation"); // false - @debug color.is-powerless(#999, "hue", $space: hsl); // true - === - @use 'sass:color' - - @debug color.is-powerless(hsl(180deg 0% 40%), "hue") // true - @debug color.is-powerless(hsl(180deg 0% 40%), "saturation") // false - @debug color.is-powerless(#999, "hue", $space: hsl) // true - {% endcodeExample %} -{% endfunction %} - -{% function 'color.mix($color1, $color2, $weight: 50%, $method: null)', 'mix($color1, $color2, $weight: 50%, $method: null)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$method"' %}{% endcompatibility %} - - Returns a color that's a mixture of `$color1` and `$color2` using `$method`, - which is the name of a color space, optionally followed by a [hue - interpolation method] if it's a polar color space (`hsl`, `hwb`, `lch`, or - `oklch`). - - [hue interpolation method]: https://developer.mozilla.org/en-US/docs/Web/CSS/hue-interpolation-method - - This uses the same algorithm to mix colors as [the CSS `color-mix()` - function]. This also means that if either color has a [missing channel] in the - interpolation space, it will take on the corresponding channel value from the - other color. This always returns a color in `$color1`'s space. - - [the CSS `color-mix()` function]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix - [missing channel]: /documentation/values/colors#missing-channels - - The `$weight` must be a number between `0%` and `100%` (inclusive). A larger - weight indicates that more of `$color1` should be used, and a smaller weight - indicates that more of `$color2` should be used. - - {% headsUp %} - For historical reasons, `$method` is optional if `$color1` and `$color2` are - both in [legacy color spaces]. In this case, color mixing is done using the - same algorithm that Sass used historically, in which both the `$weight` and - the relative opacity of each color determines how much of each color is in - the result. - - [legacy color spaces]: /documentation/values/colors#legacy-color-spaces - {% endheadsUp %} - - {% codeExample 'color-mix', false %} - @use 'sass:color'; - - @debug color.mix(#036, #d2e1dd, $method: rgb); // #698aa2 - @debug color.mix(#036, #d2e1dd, $method: oklch); // rgb(87.864037264, 140.601918773, 154.2876826946) - @debug color.mix( - color(rec2020 1 0.7 0.1), - color(rec2020 0.8 none 0.3), - $weight: 75%, - $method: rec2020 - ); // color(rec2020 0.95 0.7 0.15) - @debug color.mix( - oklch(80% 20% 0deg), - oklch(50% 10% 120deg), - $method: oklch longer hue - ); // oklch(65% 0.06 240deg) - === - @use 'sass:color'; - - @debug color.mix(#036, #d2e1dd, $method: rgb) // #698aa2 - @debug color.mix(#036, #d2e1dd, $method: oklch) // rgb(87.864037264, 140.601918773, 154.2876826946) - @debug color.mix(color(rec2020 1 0.7 0.1), color(rec2020 0.8 none 0.3), $weight: 75%, $method: rec2020) // color(rec2020 0.95 0.7 0.15) - - - - - - @debug color.mix(oklch(80% 20% 0deg), oklch(50% 10% 120deg), $method: oklch longer hue) // oklch(65% 0.06 240deg) - {% endcodeExample %} -{% endfunction %} - -{% function 'color.same($color1, $color2)', 'returns:boolean' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Returns whether `$color1` and `$color2` visually render as the same color. - Unlike `==`, this considers colors to be equivalent even if they're in - different color spaces as long as they represent the same color value in the - `xyz` color space. This treats [missing channels] as equivalent to zero. - - [missing channels]: /documentation/values/colors#missing-channels - - {% codeExample 'color-same', false %} - @use 'sass:color'; - - @debug color.same(#036, #036); // true - @debug color.same(#036, #037); // false - @debug color.same(#036, color.to-space(#036, oklch)); // true - @debug color.same(hsl(none 50% 50%), hsl(0deg 50% 50%)); // true - === - @use 'sass:color' - - @debug color.same(#036, #036) // true - @debug color.same(#036, #037) // false - @debug color.same(#036, color.to-space(#036, oklch)) // true - @debug color.same(hsl(none 50% 50%), hsl(0deg 50% 50%)) // true - {% endcodeExample %} -{% endfunction %} - -{% capture color_scale %} - color.scale($color, - $red: null, $green: null, $blue: null, - $saturation: null, $lightness: null, - $whiteness: null, $blackness: null, - $x: null, $y: null, $z: null, - $chroma: null, - $alpha: null, - $space: null) -{% endcapture %} - -{% function color_scale, 'scale-color(...)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "$x, $y, $z, $chroma, and $space"' %}{% endcompatibility %} - {% compatibility 'dart: "1.28.0"', 'libsass: false', 'ruby: false', 'feature: "$whiteness and $blackness"' %}{% endcompatibility %} - - Fluidly scales one or more properties of `$color`. - - Each keyword argument must be a number between `-100%` and `100%` (inclusive). - This indicates how far the corresponding property should be moved from its - original position towards the maximum (if the argument is positive) or the - minimum (if the argument is negative). This means that, for example, - `$lightness: 50%` will make all colors `50%` closer to maximum lightness - without making them fully white. By default, this can only scale colors in - `$color`'s space, but a different color space can be passed as `$space` to - scale channels there instead. This always returns a color in the same space as - `$color`. - - {% headsUp %} - For historical reasons, if `$color` is in a [legacy color space], _any_ - legacy color space channels can be scaled. However, it's an error to specify - an RGB channel (`$red`, `$green`, and/or `$blue`) at the same time as an HSL - channel (`$saturation`, and/or `$lightness`), or either of those at the same - time as an [HWB] channel (`$hue`, `$whiteness`, and/or `$blackness`). - - [legacy color space]: /documentation/values/colors#legacy-color-spaces - [HWB]: https://en.wikipedia.org/wiki/HWB_color_model - - Even so, it's a good idea to pass `$space` explicitly even for legacy colors. - {% endheadsUp %} - - [HWB]: https://en.wikipedia.org/wiki/HWB_color_model - - See also: - - * [`color.adjust()`](#adjust) for changing a color's properties by fixed - amounts. - * [`color.change()`](#change) for setting a color's properties. - - {% codeExample 'color-scale', false %} - @use 'sass:color'; - - @debug color.scale(#6b717f, $red: 15%); // rgb(129.2, 113, 127) - @debug color.scale(#d2e1dd, $lightness: -10%, $space: oklch); - // rgb(181.2580722731, 195.8949200496, 192.0059024063) - @debug color.scale(oklch(80% 20% 120deg), $chroma: 50%, $alpha: -40%); - // oklch(80% 0.24 120deg / 0.6) - === - @use 'sass:color' - - @debug color.scale(#6b717f, $red: 15%) // rgb(129.2, 113, 127) - @debug color.scale(#d2e1dd, $lightness: -10%, $space: oklch) - // rgb(181.2580722731, 195.8949200496, 192.0059024063) - @debug color.scale(oklch(80% 20% 120deg), $chroma: 50%, $alpha: -40%) - // oklch(80% 0.24 120deg / 0.6) - {% endcodeExample %} -{% endfunction %} - -{% function 'color.space($color)', 'returns:unquoted string' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Returns the name of `$color`'s space as an unquoted string. - - {% codeExample 'color-space', false %} - @use 'sass:color'; - - @debug color.space(#036); // rgb - @debug color.space(hsl(120deg 40% 50%)); // hsl - @debug color.space(color(xyz-d65 0.1 0.2 0.3)); // xyz - === - @use 'sass:color' - - @debug color.space(#036) // rgb - @debug color.space(hsl(120deg 40% 50%)) // hsl - @debug color.space(color(xyz-d65 0.1 0.2 0.3)) // xyz - {% endcodeExample %} -{% endfunction %} - -{% function 'color.to-gamut($color, $space: null, $method: null)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Returns a visually similar color to `$color` in the gamut of `$space`, which - defaults to `$color`'s space. If `$color` is already in-gamut for `$space`, - it's returned as-is. This always returns a color in` $color`'s original space. - The `$space` must be an unquoted string. - - The `$method` indicates how Sass should choose a "similar" color: - - * `local-minde`: This is the method currently recommended by the CSS Colors 4 - specification. It binary searches the Oklch chroma space of the color until - it finds a color whose clipped-to-gamut value is as close as possible to the - reduced-chroma variant. - - * `clip`: This simply clips all channels to within `$space`'s gamut, setting - them to the minimum or maximum gamut values if they're out-of-gamut. - - {% headsUp %} - The CSS working group and browser vendors are still actively discussing - alternative options for a recommended gamut-mapping algorithm. Until they - settle on a recommendation, the `$method` parameter is mandatory in - `color.to-gamut()` so that we can eventually make its default value the same - as the CSS default. - {% endheadsUp %} - - {% codeExample 'color-to-gamut', false %} - @use 'sass:color'; - - @debug color.to-gamut(#036, $method: local-minde); // #036 - @debug color.to-gamut(oklch(60% 70% 20deg), $space: rgb, $method: local-minde); - // oklch(61.2058838235% 0.2466052584 22.0773325274deg) - @debug color.to-gamut(oklch(60% 70% 20deg), $space: rgb, $method: clip); - // oklch(62.5026609544% 0.2528579741 24.1000466758deg) - === - @use 'sass:color' - - @debug color.to-gamut(#036, $method: local-minde) // #036 - @debug color.to-gamut(oklch(60% 70% 20deg), $space: rgb, $method: local-minde) - // oklch(61.2058838235% 0.2466052584 22.0773325274deg) - @debug color.to-gamut(oklch(60% 70% 20deg), $space: rgb, $method: clip) - // oklch(62.5026609544% 0.2528579741 24.1000466758deg) - {% endcodeExample %} -{% endfunction %} - -{% function 'color.to-space($color, $space)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Converts `$color` into the given `$space`, which must be an unquoted string. - - If the gamut of `$color`'s original space is wider than `$space`'s gamut, this - may return a color that's out-of-gamut for the `$space`. You can convert it to - a similar in-gamut color using [`color.to-gamut()`]. - - [`color.to-gamut()`]: #to-gamut - - This can produce colors with [missing channels], either if `$color` has an - [analogous channel] that's missing, or if the channel is [powerless] in the - destination space. In order to ensure that converting to legacy color spaces - always produces a color that's compatible with older browsers, if `$space` is - legacy this will never return a new missing channel. - - [missing channels]: /documentation/values/colors#missing-channels - [analogous channel]: https://www.w3.org/TR/css-color-4/#analogous-components - [powerless]: /documentation/values/colors#powerless-channels - - {% funFact %} - This is the only Sass function that returns a color in a different space - than the one passed in. - {% endfunFact %} - - {% codeExample 'color-to-space', false %} - @use 'sass:color'; - - @debug color.to-space(#036, display-p3); // lch(20.7457453073% 35.0389733355 273.0881809283deg) - @debug color.to-space(oklab(44% 0.09 -0.13)); // rgb(103.1328911972, 50.9728091281, 150.8382311692) - @debug color.to-space(xyz(0.8 0.1 0.1)); // color(a98-rgb 1.2177586808 -0.7828263424 0.3516847577) - @debug color.to-space(grey, lch); // lch(53.5850134522% 0 none) - @debug color.to-space(lch(none 10% 30deg), oklch); // oklch(none 0.3782382429 11.1889160032deg) - === - @use 'sass:color' - - @debug color.to-space(#036, display-p3) // lch(20.7457453073% 35.0389733355 273.0881809283deg) - @debug color.to-space(oklab(44% 0.09 -0.13)) // rgb(103.1328911972, 50.9728091281, 150.8382311692) - @debug color.to-space(xyz(0.8 0.1 0.1)) // color(a98-rgb 1.2177586808 -0.7828263424 0.3516847577) - @debug color.to-space(grey, lch) // lch(53.5850134522% 0 none) - @debug color.to-space(lch(none 10% 30deg), oklch) // oklch(none 0.3782382429 11.1889160032deg) - {% endcodeExample %} -{% endfunction %} - -## Deprecated Functions - {% function 'adjust-hue($color, $degrees)', 'returns:color' %} - Increases or decreases `$color`'s HSL hue. + Increases or decreases `$color`'s hue. The `$hue` must be a number between `-360deg` and `360deg` (inclusive) to add - to `$color`'s hue. It may be [unitless] or have any angle unit. The `$color` - must be in a [legacy color space]. + to `$color`'s hue. It may be [unitless][] but it may not have any unit other + than `deg`. [unitless]: /documentation/values/numbers#units - [legacy color space]: /documentation/values/colors#legacy-color-spaces See also [`color.adjust()`](#adjust), which can adjust any property of a color. @@ -667,8 +70,7 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% headsUp %} Because `adjust-hue()` is redundant with [`adjust()`](#adjust), it's not included directly in the new module system. Instead of `adjust-hue($color, - $amount)`, you can write [`color.adjust($color, $hue: $amount, $space: - hsl)`](#adjust). + $amount)`, you can write [`color.adjust($color, $hue: $amount)`](#adjust). {% endheadsUp %} {% codeExample 'adjust-hue' %} @@ -694,21 +96,20 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% function 'color.alpha($color)', 'alpha($color)', 'opacity($color)', 'returns:number' %} Returns the alpha channel of `$color` as a number between 0 and 1. - - The `$color` must be in a [legacy color space]. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces As a special case, this supports the Internet Explorer syntax - `alpha(opacity=20)`, for which it returns an [unquoted string]. + `alpha(opacity=20)`, for which it returns an [unquoted string][]. [unquoted string]: /documentation/values/strings#unquoted - {% headsUp %} - Because `color.alpha()` is redundant with [`color.channel()`](#channel), - it's no longer recommended. Instead of `color.alpha($color)`, you can write - [`color.channel($color, "alpha")`](#channel). - {% endheadsUp %} + See also: + + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. {% codeExample 'color-alpha' %} @use 'sass:color'; @@ -725,22 +126,22 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% endcodeExample %} {% endfunction %} -{% function 'color.blackness($color)', 'blackness($color)', 'returns:number' %} +{% function 'color.blackness($color)', 'returns:number' %} {% compatibility 'dart: "1.28.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - Returns the [HWB] blackness of `$color` as a number between `0%` and `100%`. + Returns the [HWB][] blackness of `$color` as a number between `0%` and `100%`. [HWB]: https://en.wikipedia.org/wiki/HWB_color_model - The `$color` must be in a [legacy color space]. + See also: - [legacy color space]: /documentation/values/colors#legacy-color-spaces - - {% headsUp %} - Because `color.blackness()` is redundant with [`color.channel()`](#channel), - it's no longer recommended. Instead of `color.blackness($color)`, you can - write [`color.channel($color, "blackness")`](#channel). - {% endheadsUp %} + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.whiteness()`](#whiteness) for getting a color's whiteness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. {% codeExample 'color-blackness' %} @use 'sass:color'; @@ -760,15 +161,16 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% function 'color.blue($color)', 'blue($color)', 'returns:number' %} Returns the blue channel of `$color` as a number between 0 and 255. - The `$color` must be in a [legacy color space]. + See also: - [legacy color space]: /documentation/values/colors#legacy-color-spaces - - {% headsUp %} - Because `color.blue()` is redundant with [`color.channel()`](#channel), it's - no longer recommended. Instead of `color.blue($color)`, you can write - [`color.channel($color, "blue")`](#channel). - {% endheadsUp %} + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.whiteness()`](#whiteness) for getting a color's whiteness. + * [`color.blackness()`](#blackness) for getting a color's blackness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. {% codeExample 'color-blue' %} @use 'sass:color'; @@ -785,12 +187,92 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% endcodeExample %} {% endfunction %} -{% function 'darken($color, $amount)', 'returns:color' %} - Makes `$color` darker. +{% capture color_change %} + color.change($color, + $red: null, $green: null, $blue: null, + $hue: null, $saturation: null, $lightness: null, + $whiteness: null, $blackness: null, + $alpha: null) +{% endcapture %} - The `$color` must be in a [legacy color space]. +{% function color_change, 'change-color(...)', 'returns:color' %} + {% compatibility 'dart: "1.28.0"', 'libsass: false', 'ruby: false', 'feature: "$whiteness and $blackness"' %}{% endcompatibility %} - [legacy color space]: /documentation/values/colors#legacy-color-spaces + Sets one or more properties of a color to new values. + + Uses the value passed for each keyword argument in place of the corresponding + property of the color, and returns the changed color. It's an error to specify + an RGB property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL + property (`$hue`, `$saturation`, and/or `$lightness`), or either of those at + the same time as an [HWB][] property (`$hue`, `$whiteness`, and/or + `$blackness`). + + [HWB]: https://en.wikipedia.org/wiki/HWB_color_model + + All optional arguments must be numbers. The `$red`, `$green`, and `$blue` + arguments must be [unitless][] and between 0 and 255 (inclusive). The `$hue` + argument must have either the unit `deg` or no unit. The `$saturation`, + `$lightness`, `$whiteness`, and `$blackness` arguments must be between `0%` + and `100%` (inclusive), and may not be unitless. The `$alpha` argument must be + unitless and between 0 and 1 (inclusive). + + [unitless]: /documentation/values/numbers#units + + See also: + + * [`color.scale()`](#scale) for fluidly scaling a color's properties. + * [`color.adjust()`](#adjust) for adjusting a color's properties by fixed + amounts. + + {% codeExample 'color-change' %} + @use 'sass:color'; + + @debug color.change(#6b717f, $red: 100); // #64717f + @debug color.change(#d2e1dd, $red: 100, $blue: 50); // #64e132 + @debug color.change(#998099, $lightness: 30%, $alpha: 0.5); // rgba(85, 68, 85, 0.5) + === + @use 'sass:color' + + @debug color.change(#6b717f, $red: 100) // #64717f + @debug color.change(#d2e1dd, $red: 100, $blue: 50) // #64e132 + @debug color.change(#998099, $lightness: 30%, $alpha: 0.5) // rgba(85, 68, 85, 0.5) + {% endcodeExample %} +{% endfunction %} + +{% function 'color.complement($color)', 'complement($color)', 'returns:color' %} + Returns the RGB [complement][] of `$color`. + + This is identical to [`color.adjust($color, $hue: 180deg)`](#adjust). + + [complement]: https://en.wikipedia.org/wiki/Complementary_colors + + {% codeExample 'color-complement' %} + @use 'sass:color'; + + // Hue 222deg becomes 42deg. + @debug color.complement(#6b717f); // #7f796b + + // Hue 164deg becomes 344deg. + @debug color.complement(#d2e1dd); // #e1d2d6 + + // Hue 210deg becomes 30deg. + @debug color.complement(#036); // #663300 + === + @use 'sass:color' + + // Hue 222deg becomes 42deg. + @debug color.complement(#6b717f) // #7f796b + + // Hue 164deg becomes 344deg. + @debug color.complement(#d2e1dd) // #e1d2d6 + + // Hue 210deg becomes 30deg. + @debug color.complement(#036) // #663300 + {% endcodeExample %} +{% endfunction %} + +{% function 'darken($color, $amount)', 'returns:color' %} + Makes `$color` darker. The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases the HSL lightness of `$color` by that amount. @@ -803,7 +285,7 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which Because `darken()` is usually not the best way to make a color darker, it's not included directly in the new module system. However, if you have to preserve the existing behavior, `darken($color, $amount)` can be written - [`color.adjust($color, $lightness: -$amount, $space: hsl)`](#adjust). + [`color.adjust($color, $lightness: -$amount)`](#adjust). {% codeExample 'color-darken' %} @use 'sass:color'; @@ -848,10 +330,6 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% function 'desaturate($color, $amount)', 'returns:color' %} Makes `$color` less saturated. - The `$color` must be in a [legacy color space]. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces - The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases the HSL saturation of `$color` by that amount. @@ -863,8 +341,7 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which Because `desaturate()` is usually not the best way to make a color less saturated, it's not included directly in the new module system. However, if you have to preserve the existing behavior, `desaturate($color, $amount)` - can be written [`color.adjust($color, $saturation: -$amount, $space: - hsl)`](#adjust). + can be written [`color.adjust($color, $saturation: -$amount)`](#adjust). {% codeExample 'color-desaturate' %} @use 'sass:color'; @@ -908,18 +385,39 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% endcodeExample %} {% endfunction %} +{% function 'color.grayscale($color)', 'grayscale($color)', 'returns:color' %} + Returns a gray color with the same lightness as `$color`. + + This is identical to [`color.change($color, $saturation: 0%)`](#change). + + {% codeExample 'color-grayscale' %} + @use 'sass:color'; + + @debug color.grayscale(#6b717f); // #757575 + @debug color.grayscale(#d2e1dd); // #dadada + @debug color.grayscale(#036); // #333333 + === + @use 'sass:color' + + @debug color.grayscale(#6b717f) // #757575 + @debug color.grayscale(#d2e1dd) // #dadada + @debug color.grayscale(#036) // #333333 + {% endcodeExample %} +{% endfunction %} + {% function 'color.green($color)', 'green($color)', 'returns:number' %} Returns the green channel of `$color` as a number between 0 and 255. - The `$color` must be in a [legacy color space]. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces + See also: - {% headsUp %} - Because `color.green()` is redundant with [`color.channel()`](#channel), - it's no longer recommended. Instead of `color.green($color)`, you can write - [`color.channel($color, "green")`](#channel). - {% endheadsUp %} + * [`color.red()`](#red) for getting a color's red channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.whiteness()`](#whiteness) for getting a color's whiteness. + * [`color.blackness()`](#blackness) for getting a color's blackness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. {% codeExample 'color-green' %} @use 'sass:color'; @@ -939,15 +437,16 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% function 'color.hue($color)', 'hue($color)', 'returns:number' %} Returns the hue of `$color` as a number between `0deg` and `360deg`. - The `$color` must be in a [legacy color space]. + See also: - [legacy color space]: /documentation/values/colors#legacy-color-spaces - - {% headsUp %} - Because `color.hue()` is redundant with [`color.channel()`](#channel), it's - no longer recommended. Instead of `color.hue($color)`, you can write - [`color.channel($color, "hue")`](#channel). - {% endheadsUp %} + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.whiteness()`](#whiteness) for getting a color's whiteness. + * [`color.blackness()`](#blackness) for getting a color's blackness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. {% codeExample 'color-hue' %} @use 'sass:color'; @@ -964,12 +463,94 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% endcodeExample %} {% endfunction %} -{% function 'lighten($color, $amount)', 'returns:color' %} - Makes `$color` lighter. +{% function 'color.hwb($hue $whiteness $blackness)', 'color.hwb($hue $whiteness $blackness / $alpha)', 'color.hwb($hue, $whiteness, $blackness, $alpha: 1)', 'returns:color' %} + {% compatibility 'dart: "1.28.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} + + Returns a color with the given [hue, whiteness, and blackness][] and the given + alpha channel. + + [hue, whiteness, and blackness]: https://en.wikipedia.org/wiki/HWB_color_model + + The hue is a number between `0deg` and `360deg` (inclusive). The whiteness and + blackness are numbers between `0%` and `100%` (inclusive). The hue may be + [unitless][], but the whiteness and blackness must have unit `%`. The alpha + channel can be specified as either a unitless number between 0 and 1 + (inclusive), or a percentage between `0%` and `100%` (inclusive). + + [unitless]: /documentation/values/numbers#units + + {% headsUp %} + Sass's [special parsing rules][] for slash-separated values make it + difficult to pass variables for `$blackness` or `$alpha` when using the + `color.hwb($hue $whiteness $blackness / $alpha)` signature. Consider using + `color.hwb($hue, $whiteness, $blackness, $alpha)` instead. + + [special parsing rules]: /documentation/operators/numeric#slash-separated-values + {% endheadsUp %} + + {% codeExample 'color-hwb' %} + @use 'sass:color'; + + @debug color.hwb(210, 0%, 60%); // #036 + @debug color.hwb(34, 89%, 5%); // #f2ece4 + @debug color.hwb(210 0% 60% / 0.5); // rgba(0, 51, 102, 0.5) + === + @use 'sass:color' + + @debug color.hwb(210, 0%, 60%) // #036 + @debug color.hwb(34, 89%, 5%) // #f2ece4 + @debug color.hwb(210 0% 60% / 0.5) // rgba(0, 51, 102, 0.5) + {% endcodeExample %} +{% endfunction %} + +{% function 'color.ie-hex-str($color)', 'ie-hex-str($color)', 'returns:unquoted string' %} + Returns an unquoted string that represents `$color` in the `#AARRGGBB` format + expected by Internet Explorer's [`-ms-filter`][] property. + + [`-ms-filter`]: https://learn.microsoft.com/en-us/previous-versions/ms530752(v=vs.85) + + {% codeExample 'color-ie-hex-str' %} + @use 'sass:color'; + + @debug color.ie-hex-str(#b37399); // #FFB37399 + @debug color.ie-hex-str(#808c99); // #FF808C99 + @debug color.ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4 + === + @use 'sass:color' + + @debug color.ie-hex-str(#b37399); // #FFB37399 + @debug color.ie-hex-str(#808c99); // #FF808C99 + @debug color.ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4 + {% endcodeExample %} +{% endfunction %} + +{% function 'color.invert($color, $weight: 100%)', 'invert($color, $weight: 100%)', 'returns:color' %} + Returns the inverse or [negative][] of `$color`. + + [negative]: https://en.wikipedia.org/wiki/Negative_(photography) + + The `$weight` must be a number between `0%` and `100%` (inclusive). A higher + weight means the result will be closer to the negative, and a lower weight + means it will be closer to `$color`. Weight `50%` will always produce + `#808080`. + + {% codeExample 'color-invert' %} + @use 'sass:color'; + + @debug color.invert(#b37399); // #4c8c66 + @debug color.invert(black); // white + @debug color.invert(#550e0c, 20%); // #663b3a + === + @use 'sass:color' - The `$color` must be in a [legacy color space]. + @debug color.invert(#b37399) // #4c8c66 + @debug color.invert(black) // white + @debug color.invert(#550e0c, 20%) // #663b3a + {% endcodeExample %} +{% endfunction %} - [legacy color space]: /documentation/values/colors#legacy-color-spaces +{% function 'lighten($color, $amount)', 'returns:color' %} + Makes `$color` lighter. The `$amount` must be a number between `0%` and `100%` (inclusive). Increases the HSL lightness of `$color` by that amount. @@ -982,7 +563,7 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which Because `lighten()` is usually not the best way to make a color lighter, it's not included directly in the new module system. However, if you have to preserve the existing behavior, `lighten($color, $amount)` can be written - [`adjust($color, $lightness: $amount, $space: hsl)`](#adjust). + [`adjust($color, $lightness: $amount)`](#adjust). {% codeExample 'color-lighten' %} @use 'sass:color'; @@ -1027,15 +608,16 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% function 'color.lightness($color)', 'lightness($color)', 'returns:number' %} Returns the HSL lightness of `$color` as a number between `0%` and `100%`. - The `$color` must be in a [legacy color space]. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces + See also: - {% headsUp %} - Because `color.lightness()` is redundant with [`color.channel()`](#channel), - it's no longer recommended. Instead of `color.lightness($color)`, you can write - [`color.channel($color, "lightness")`](#channel). - {% endheadsUp %} + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.whiteness()`](#whiteness) for getting a color's whiteness. + * [`color.blackness()`](#blackness) for getting a color's blackness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. {% codeExample 'color-lightness' %} @use 'sass:color'; @@ -1052,12 +634,34 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% endcodeExample %} {% endfunction %} -{% function 'opacify($color, $amount)', 'fade-in($color, $amount)', 'returns:color' %} - Makes `$color` more opaque. +{% function 'color.mix($color1, $color2, $weight: 50%)', 'mix($color1, $color2, $weight: 50%)', 'returns:color' %} + Returns a color that's a mixture of `$color1` and `$color2`. + + Both the `$weight` and the relative opacity of each color determines how much + of each color is in the result. The `$weight` must be a number between `0%` + and `100%` (inclusive). A larger weight indicates that more of `$color1` + should be used, and a smaller weight indicates that more of `$color2` should + be used. - The `$color` must be in a [legacy color space]. + {% codeExample 'color-mix' %} + @use 'sass:color'; + + @debug color.mix(#036, #d2e1dd); // #698aa2 + @debug color.mix(#036, #d2e1dd, 75%); // #355f84 + @debug color.mix(#036, #d2e1dd, 25%); // #9eb6bf + @debug color.mix(rgba(242, 236, 228, 0.5), #6b717f); // rgba(141, 144, 152, 0.75) + === + @use 'sass:color' - [legacy color space]: /documentation/values/colors#legacy-color-spaces + @debug color.mix(#036, #d2e1dd) // #698aa2 + @debug color.mix(#036, #d2e1dd, 75%) // #355f84 + @debug color.mix(#036, #d2e1dd, 25%) // #9eb6bf + @debug color.mix(rgba(242, 236, 228, 0.5), #6b717f) // rgba(141, 144, 152, 0.75) + {% endcodeExample %} +{% endfunction %} + +{% function 'opacify($color, $amount)', 'fade-in($color, $amount)', 'returns:color' %} + Makes `$color` more opaque. The `$amount` must be a number between `0` and `1` (inclusive). Increases the alpha channel of `$color` by that amount. @@ -1107,15 +711,16 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% function 'color.red($color)', 'red($color)', 'returns:number' %} Returns the red channel of `$color` as a number between 0 and 255. - The `$color` must be in a [legacy color space]. + See also: - [legacy color space]: /documentation/values/colors#legacy-color-spaces - - {% headsUp %} - Because `color.red()` is redundant with [`color.channel()`](#channel), it's - no longer recommended. Instead of `color.red($color)`, you can write - [`color.channel($color, "red")`](#channel). - {% endheadsUp %} + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.whiteness()`](#whiteness) for getting a color's whiteness. + * [`color.blackness()`](#blackness) for getting a color's blackness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. {% codeExample 'color-red' %} @use 'sass:color'; @@ -1135,10 +740,6 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% function 'color.saturate($color, $amount)', 'saturate($color, $amount)', 'returns:color' %} Makes `$color` more saturated. - The `$color` must be in a [legacy color space]. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces - The `$amount` must be a number between `0%` and `100%` (inclusive). Increases the HSL saturation of `$color` by that amount. @@ -1150,7 +751,7 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which Because `saturate()` is usually not the best way to make a color more saturated, it's not included directly in the new module system. However, if you have to preserve the existing behavior, `saturate($color, $amount)` can - be written [`adjust($color, $saturation: $amount, $space: hsl)`](#adjust). + be written [`adjust($color, $saturation: $amount)`](#adjust). {% codeExample 'color-saturate' %} @use 'sass:color'; @@ -1197,16 +798,16 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% function 'color.saturation($color)', 'saturation($color)', 'returns:number' %} Returns the HSL saturation of `$color` as a number between `0%` and `100%`. - The `$color` must be in a [legacy color space]. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces + See also: - {% headsUp %} - Because `color.saturation()` is redundant with - [`color.channel()`](#channel), it's no longer recommended. Instead of - `color.saturation($color)`, you can write - [`color.channel($color, "saturation")`](#channel). - {% endheadsUp %} + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.blue()`](#blue) for getting a color's blue channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.whiteness()`](#whiteness) for getting a color's whiteness. + * [`color.blackness()`](#blackness) for getting a color's blackness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. {% codeExample 'color-saturation' %} @use 'sass:color'; @@ -1223,12 +824,56 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% endcodeExample %} {% endfunction %} -{% function 'transparentize($color, $amount)', 'fade-out($color, $amount)', 'returns:color' %} - Makes `$color` more transparent. +{% capture color_scale %} + color.scale($color, + $red: null, $green: null, $blue: null, + $saturation: null, $lightness: null, + $whiteness: null, $blackness: null, + $alpha: null) +{% endcapture %} + +{% function color_scale, 'scale-color(...)', 'returns:color' %} + {% compatibility 'dart: "1.28.0"', 'libsass: false', 'ruby: false', 'feature: "$whiteness and $blackness"' %}{% endcompatibility %} - The `$color` must be in a [legacy color space]. + Fluidly scales one or more properties of `$color`. + + Each keyword argument must be a number between `-100%` and `100%` (inclusive). + This indicates how far the corresponding property should be moved from its + original position towards the maximum (if the argument is positive) or the + minimum (if the argument is negative). This means that, for example, + `$lightness: 50%` will make all colors `50%` closer to maximum lightness + without making them fully white. + + It's an error to specify an RGB property (`$red`, `$green`, and/or `$blue`) at + the same time as an HSL property (`$saturation`, and/or `$lightness`), or + either of those at the same time as an [HWB][] property (`$whiteness`, and/or + `$blackness`). + + [HWB]: https://en.wikipedia.org/wiki/HWB_color_model + + See also: + + * [`color.adjust()`](#adjust) for changing a color's properties by fixed + amounts. + * [`color.change()`](#change) for setting a color's properties. + + {% codeExample 'color-scale' %} + @use 'sass:color'; + + @debug color.scale(#6b717f, $red: 15%); // #81717f + @debug color.scale(#d2e1dd, $lightness: -10%, $saturation: 10%); // #b3d4cb + @debug color.scale(#998099, $alpha: -40%); // rgba(153, 128, 153, 0.6) + === + @use 'sass:color' - [legacy color space]: /documentation/values/colors#legacy-color-spaces + @debug color.scale(#6b717f, $red: 15%) // #81717f + @debug color.scale(#d2e1dd, $lightness: -10%, $saturation: 10%) // #b3d4cb + @debug color.scale(#998099, $alpha: -40%) // rgba(153, 128, 153, 0.6) + {% endcodeExample %} +{% endfunction %} + +{% function 'transparentize($color, $amount)', 'fade-out($color, $amount)', 'returns:color' %} + Makes `$color` more transparent. The `$amount` must be a number between `0` and `1` (inclusive). Decreases the alpha channel of `$color` by that amount. @@ -1242,8 +887,8 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which Because `transparentize()` is usually not the best way to make a color more transparent, it's not included directly in the new module system. However, if you have to preserve the existing behavior, `transparentize($color, - $amount)` can be written [`color.adjust($color, $alpha: -$amount, - $space: hsl)`](#adjust). + $amount)` can be written [`color.adjust($color, $alpha: + -$amount)`](#adjust). {% codeExample 'transparentize' %} @use 'sass:color'; @@ -1280,19 +925,19 @@ Returns whether `$color`'s `$channel` is [powerless] in `$space`, which {% function 'color.whiteness($color)', 'returns:number' %} {% compatibility 'dart: "1.28.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - Returns the [HWB] whiteness of `$color` as a number between `0%` and `100%`. + Returns the [HWB][] whiteness of `$color` as a number between `0%` and `100%`. [HWB]: https://en.wikipedia.org/wiki/HWB_color_model - The `$color` must be in a [legacy color space]. - - [legacy color space]: /documentation/values/colors#legacy-color-spaces + See also: - {% headsUp %} - Because `color.whiteness()` is redundant with [`color.channel()`](#channel), - it's no longer recommended. Instead of `color.whiteness($color)`, you can - write [`color.channel($color, "whiteness")`](#channel). - {% endheadsUp %} + * [`color.red()`](#red) for getting a color's red channel. + * [`color.green()`](#green) for getting a color's green channel. + * [`color.hue()`](#hue) for getting a color's hue. + * [`color.saturation()`](#saturation) for getting a color's saturation. + * [`color.lightness()`](#lightness) for getting a color's lightness. + * [`color.blackness()`](#blackness) for getting a color's blackness. + * [`color.alpha()`](#alpha) for getting a color's alpha channel. {% codeExample 'color-whiteness' %} @use 'sass:color'; diff --git a/source/documentation/modules/index.md b/source/documentation/modules/index.md index 39fe9329f..76e1c3a23 100644 --- a/source/documentation/modules/index.md +++ b/source/documentation/modules/index.md @@ -83,46 +83,6 @@ Sass provides the following built-in modules: ## Global Functions -{% funFact %} - You can pass [special functions] like `calc()` or `var()` in place of any - argument to a global color constructor. You can even use `var()` in place of - multiple arguments, since it might be replaced by multiple values! When a - color function is called this way, it returns an unquoted string using the - same signature it was called with. - - [special functions]: /documentation/syntax/special-functions - - {% codeExample 'color-special', false %} - @debug rgb(0 51 102 / var(--opacity)); // rgb(0 51 102 / var(--opacity)) - @debug color(display-p3 var(--peach)); // color(display-p3 var(--peach)) - === - @debug rgb(0 51 102 / var(--opacity)) // rgb(0 51 102 / var(--opacity)) - @debug color(display-p3 var(--peach)) // color(display-p3 var(--peach)) - {% endcodeExample %} -{% endfunFact %} - -{% function 'color($space $channel1 $channel2 $channel3)', 'color($space $channel1 $channel2 $channel3 / $alpha)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Returns a color in the given color space with the given channel values. - - This supports the color spaces `srgb`, `srgb-linear`, `display-p3`, `a98-rgb`, - `prophoto-rgb`, `rec2020`, `xyz`, and `xyz-d50`, as well as `xyz-d65` which is - an alias for `xyz`. For all spaces, the channels are numbers between 0 and 1 - (inclusive) or percentages between `0%` and `100%` (inclusive). - - If any color channel is outside the range 0 to 1, this represents a color - outside the standard gamut for its color space. - - {% codeExample 'hsl', false %} - @debug color(srgb 0.1 0.6 1); // color(srgb 0.1 0.6 1) - @debug color(xyz 30% 0% 90% / 50%); // color(xyz 0.3 0 0.9 / 50%) - === - @debug color(srgb 0.1 0.6 1) // color(srgb 0.1 0.6 1) - @debug color(xyz 30% 0% 90% / 50%) // color(xyz 0.3 0 0.9 / 50%) - {% endcodeExample %} -{% endfunction %} - {% function 'hsl($hue $saturation $lightness)', 'hsl($hue $saturation $lightness / $alpha)', 'hsl($hue, $saturation, $lightness, $alpha: 1)', 'hsla($hue $saturation $lightness)', 'hsla($hue $saturation $lightness / $alpha)', 'hsla($hue, $saturation, $lightness, $alpha: 1)', 'returns:color' %} {% compatibility 'dart: "1.15.0"', 'libsass: false', 'ruby: false', 'feature: "Level 4 Syntax"' %} LibSass and Ruby Sass only support the following signatures: @@ -146,15 +106,28 @@ Sass provides the following built-in modules: [hue, saturation, and lightness]: https://en.wikipedia.org/wiki/HSL_and_HSV The hue is a number between `0deg` and `360deg` (inclusive) and may be - unitless. The saturation and lightness are typically numbers between `0%` and - `100%` (inclusive) and may *not* be unitless. The alpha channel can be - specified as either a unitless number between 0 and 1 (inclusive), or a - percentage between `0%` and `100%` (inclusive). - - A hue outside `0deg` and `360deg` is equivalent to `$hue % 360deg`. A - saturation less than `0%` is clamped to `0%`. A saturation above `100%` or a - lightness outside `0%` and `100%` are both allowed, and represent colors - outside the standard RGB gamut. + unitless. The saturation and lightness are numbers between `0%` and `100%` + (inclusive) and may *not* be unitless. The alpha channel can be specified as + either a unitless number between 0 and 1 (inclusive), or a percentage between + `0%` and `100%` (inclusive). + + {% funFact %} + You can pass [special functions][] like `calc()` or `var()` in place of any + argument to `hsl()`. You can even use `var()` in place of multiple + arguments, since it might be replaced by multiple values! When a color + function is called this way, it returns an unquoted string using the same + signature it was called with. + + [special functions]: /documentation/syntax/special-functions + + {% codeExample 'hsl-special', false %} + @debug hsl(210deg 100% 20% / var(--opacity)); // hsl(210deg 100% 20% / var(--opacity)) + @debug hsla(var(--peach), 20%); // hsla(var(--peach), 20%) + === + @debug hsl(210deg 100% 20% / var(--opacity)) // hsl(210deg 100% 20% / var(--opacity)) + @debug hsla(var(--peach), 20%) // hsla(var(--peach), 20%) + {% endcodeExample %} + {% endfunFact %} {% headsUp %} Sass's [special parsing rules][] for slash-separated values make it @@ -167,65 +140,14 @@ Sass provides the following built-in modules: {% codeExample 'hsl', false %} @debug hsl(210deg 100% 20%); // #036 + @debug hsl(34, 35%, 92%); // #f2ece4 @debug hsl(210deg 100% 20% / 50%); // rgba(0, 51, 102, 0.5) - @debug hsla(34, 35%, 92%, 0.2); // rgba(241.74, 235.552, 227.46, 0.2) + @debug hsla(34, 35%, 92%, 0.2); // rgba(242, 236, 228, 0.2) === @debug hsl(210deg 100% 20%) // #036 + @debug hsl(34, 35%, 92%) // #f2ece4 @debug hsl(210deg 100% 20% / 50%) // rgba(0, 51, 102, 0.5) - @debug hsla(34, 35%, 92%, 0.2) // rgba(241.74, 235.552, 227.46, 0.2) - {% endcodeExample %} -{% endfunction %} - -{% function 'if($condition, $if-true, $if-false)' %} - Returns `$if-true` if `$condition` is [truthy][], and `$if-false` otherwise. - - This function is special in that it doesn't even evaluate the argument that - isn't returned, so it's safe to call even if the unused argument would throw - an error. - - [truthy]: /documentation/at-rules/control/if#truthiness-and-falsiness - - {% codeExample 'debug', false %} - @debug if(true, 10px, 15px); // 10px - @debug if(false, 10px, 15px); // 15px - @debug if(variable-defined($var), $var, null); // null - === - @debug if(true, 10px, 15px) // 10px - @debug if(false, 10px, 15px) // 15px - @debug if(variable-defined($var), $var, null) // null - {% endcodeExample %} -{% endfunction %} - -{% function 'hwb($hue $whiteness $blackness)', 'hwb($hue $whiteness $blackness / $alpha)', 'color.hwb($hue $whiteness $blackness)', 'color.hwb($hue $whiteness $blackness / $alpha)', 'color.hwb($hue, $whiteness, $blackness, $alpha: 1)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Returns a color with the given [hue, whiteness, and blackness] and the - given alpha channel. - - [hue, whiteness, and blackness]: https://en.wikipedia.org/wiki/HWB_color_model - - The hue is a number between `0deg` and `360deg` (inclusive) and may be - unitless. The whiteness and blackness are numbers typically between `0%` and - `100%` (inclusive) and may *not* be unitless. The alpha channel can be - specified as either a unitless number between 0 and 1 (inclusive), or a - percentage between `0%` and `100%` (inclusive). - - A hue outside `0deg` and `360deg` is equivalent to `$hue % 360deg`. If - `$whiteness + $blackness > 100%`, the two values are scaled so that they add - up to `100%`. If `$whiteness`, `$blackness`, or both are less than `0%`, this - represents a color outside the standard RGB gamut. - - {% headsUp %} - The `color.hwb()` variants are deprecated. New Sass code should use the - global `hwb()` function instead. - {% endheadsUp %} - - {% codeExample 'hwb', false %} - @debug hwb(210deg 0% 60%); // #036 - @debug hwb(210 0% 60% / 0.5); // rgba(0, 51, 102, 0.5) - === - @debug hwb(210deg 0% 60%) // #036 - @debug hwb(210 0% 60% / 0.5) // rgba(0, 51, 102, 0.5) + @debug hsla(34, 35%, 92%, 0.2) // rgba(242, 236, 228, 0.2) {% endcodeExample %} {% endfunction %} @@ -249,129 +171,6 @@ Sass provides the following built-in modules: {% endcodeExample %} {% endfunction %} -{% function 'lab($lightness $a $b)', 'lab($lightness $a $b / $alpha)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Returns a color with the given [lightness, a, b], and alpha channels. - - [hue, whiteness, and blackness]: https://en.wikipedia.org/wiki/CIELAB_color_space - - The lightness is a number between `0%` and `100%` (inclusive) and may be - unitless. The a and b channels can be specified as either [unitless] numbers - between -125 and 125 (inclusive), or percentages between `-100%` and `100%` - (inclusive). The alpha channel can be specified as either a unitless number - between 0 and 1 (inclusive), or a percentage between `0%` and `100%` - (inclusive). - - [unitless]: /documentation/values/numbers#units - - A lightness outside the range `0%` and `100%` is clamped to be within that - range. If the a or b channels are outside the range `-125` to `125`, this - represents a color outside the standard CIELAB gamut. - - {% codeExample 'lab', false %} - @debug lab(50% -20 30); // lab(50% -20 30) - @debug lab(80% 0% 20% / 0.5); // lab(80% 0 25 / 0.5); - === - @debug lab(50% -20 30) // lab(50% -20 30) - @debug lab(80% 0% 20% / 0.5) // lab(80% 0 25 / 0.5); - {% endcodeExample %} -{% endfunction %} - -{% function 'lch($lightness $chroma $hue)', 'lch($lightness $chroma $hue / $alpha)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Returns a color with the given [lightness, chroma, and hue], and the given - alpha channel. - - [hue, whiteness, and blackness]: https://en.wikipedia.org/wiki/CIELAB_color_space#Cylindrical_model - - The lightness is a number between `0%` and `100%` (inclusive) and may be - unitless. The chroma channel can be specified as either a [unitless] number - between 0 and 150 (inclusive), or a percentage between `0%` and `100%` - (inclusive). The hue is a number between `0deg` and `360deg` (inclusive) and - may be unitless. The alpha channel can be specified as either a unitless - number between 0 and 1 (inclusive), or a percentage between `0%` and `100%` - (inclusive). - - [unitless]: /documentation/values/numbers#units - - A lightness outside the range `0%` and `100%` is clamped to be within that - range. A chroma below 0 is clamped to 0, and a chroma above 150 represents a - color outside the standard CIELAB gamut. A hue outside `0deg` and `360deg` is - equivalent to `$hue % 360deg`. - - {% codeExample 'lch', false %} - @debug lch(50% 10 270deg); // lch(50% 10 270deg) - @debug lch(80% 50% 0.2turn / 0.5); // lch(80% 75 72deg / 0.5); - === - @debug lch(50% 10 270deg) // lch(50% 10 270deg) - @debug lch(80% 50% 0.2turn / 0.5) // lch(80% 75 72deg / 0.5); - {% endcodeExample %} -{% endfunction %} - -{% function 'oklab($lightness $a $b)', 'oklab($lightness $a $b / $alpha)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Returns a color with the given [perceptually-uniform lightness, a, b], and - alpha channels. - - [perceptually-uniform lightness, a, b]: https://bottosson.github.io/posts/oklab/ - - The lightness is a number between `0%` and `100%` (inclusive) and may be - unitless. The a and b channels can be specified as either [unitless] numbers - between -0.4 and 0.4 (inclusive), or percentages between `-100%` and `100%` - (inclusive). The alpha channel can be specified as either a unitless number - between 0 and 1 (inclusive), or a percentage between `0%` and `100%` - (inclusive). - - [unitless]: /documentation/values/numbers#units - - A lightness outside the range `0%` and `100%` is clamped to be within that - range. If the a or b channels are outside the range `-0.4` to `0.4`, this - represents a color outside the standard Oklab gamut. - - {% codeExample 'oklab', false %} - @debug oklab(50% -0.1 0.15); // oklab(50% -0.1 0.15) - @debug oklab(80% 0% 20% / 0.5); // oklab(80% 0 0.08 / 0.5) - === - @debug oklab(50% -0.1 0.15) // oklab(50% -0.1 0.15) - @debug oklab(80% 0% 20% / 0.5) // oklab(80% 0 0.08 / 0.5) - {% endcodeExample %} -{% endfunction %} - -{% function 'oklch($lightness $chroma $hue)', 'oklch($lightness $chroma $hue / $alpha)', 'returns:color' %} - {% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false' %}{% endcompatibility %} - - Returns a color with the given [perceptually-uniform lightness, chroma, and - hue], and the given alpha channel. - - [hue, whiteness, and blackness]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch - - The lightness is a number between `0%` and `100%` (inclusive) and may be - unitless. The chroma channel can be specified as either a [unitless] number - between 0 and 0.4 (inclusive), or a percentage between `0%` and `100%` - (inclusive). The hue is a number between `0deg` and `360deg` (inclusive) and - may be unitless. The alpha channel can be specified as either a unitless - number between 0 and 1 (inclusive), or a percentage between `0%` and `100%` - (inclusive). - - [unitless]: /documentation/values/numbers#units - - A lightness outside the range `0%` and `100%` is clamped to be within that - range. A chroma below 0 is clamped to 0, and a chroma above 0.4 represents a - color outside the standard Oklab gamut. A hue outside `0deg` and `360deg` is - equivalent to `$hue % 360deg`. - - {% codeExample 'oklch', false %} - @debug oklch(50% 0.3 270deg); // oklch(50% 0.3 270deg) - @debug oklch(80% 50% 0.2turn / 0.5); // oklch(80% 0.2 72deg / 0.5); - === - @debug oklch(50% 0.3 270deg) // oklch(50% 0.3 270deg) - @debug oklch(80% 50% 0.2turn / 0.5) // oklch(80% 0.2 72deg / 0.5); - {% endcodeExample %} -{% endfunction %} - {% function 'rgb($red $green $blue)', 'rgb($red $green $blue / $alpha)', 'rgb($red, $green, $blue, $alpha: 1)', 'rgb($color, $alpha)', 'rgba($red $green $blue)', 'rgba($red $green $blue / $alpha)', 'rgba($red, $green, $blue, $alpha: 1)', 'rgba($color, $alpha)', 'returns:color' %} {% compatibility 'dart: "1.15.0"', 'libsass: false', 'ruby: false', 'feature: "Level 4 Syntax"' %} LibSass and Ruby Sass only support the following signatures: @@ -393,15 +192,30 @@ Sass provides the following built-in modules: If `$red`, `$green`, `$blue`, and optionally `$alpha` are passed, returns a color with the given red, green, blue, and alpha channels. - Each channel can be specified as either a [unitless] number between 0 and + Each channel can be specified as either a [unitless][] number between 0 and 255 (inclusive), or a percentage between `0%` and `100%` (inclusive). The alpha channel can be specified as either a unitless number between 0 and 1 (inclusive), or a percentage between `0%` and `100%` (inclusive). [unitless]: /documentation/values/numbers#units - If any color channel is outside the range 0 to 255, this represents a color - outside the standard RGB gamut. + {% funFact %} + You can pass [special functions][] like `calc()` or `var()` in place of any + argument to `rgb()`. You can even use `var()` in place of multiple + arguments, since it might be replaced by multiple values! When a color + function is called this way, it returns an unquoted string using the same + signature it was called with. + + [special functions]: /documentation/syntax/special-functions + + {% codeExample 'rgb-special', false %} + @debug rgb(0 51 102 / var(--opacity)); // rgb(0 51 102 / var(--opacity)) + @debug rgba(var(--peach), 0.2); // rgba(var(--peach), 0.2) + === + @debug rgb(0 51 102 / var(--opacity)) // rgb(0 51 102 / var(--opacity)) + @debug rgba(var(--peach), 0.2) // rgba(var(--peach), 0.2) + {% endcodeExample %} + {% endfunFact %} {% headsUp %} Sass's [special parsing rules][] for slash-separated values make it diff --git a/source/documentation/operators/equality.md b/source/documentation/operators/equality.md index ac66ba556..bbee2c5d7 100644 --- a/source/documentation/operators/equality.md +++ b/source/documentation/operators/equality.md @@ -23,9 +23,7 @@ different types: their values are equal when their units are converted between one another. * [Strings][] are unusual in that [unquoted][] and [quoted][] strings with the same contents are considered equal. -* [Colors] are equal if they're in the same [color space] and have the same - channel values, *or* if they're both in [legacy color spaces] and have the - same RGBA channel values. +* [Colors][] are equal if they have the same red, green, blue, and alpha values. * [Lists][] are equal if their contents are equal. Comma-separated lists aren't equal to space-separated lists, and bracketed lists aren't equal to unbracketed lists. @@ -42,8 +40,6 @@ different types: [quoted]: /documentation/values/strings#quoted [unquoted]: /documentation/values/strings#unquoted [Colors]: /documentation/values/colors -[color space]: /documentation/values/colors#color-spaces -[legacy color spaces]: /documentation/values/colors#legacy-color-spaces [Lists]: /documentation/values/lists [`true`, `false`]: /documentation/values/booleans [`null`]: /documentation/values/null diff --git a/source/documentation/values/colors.md b/source/documentation/values/colors.md index 227fa2c8c..0309d1041 100644 --- a/source/documentation/values/colors.md +++ b/source/documentation/values/colors.md @@ -1,347 +1,77 @@ --- title: Colors -table_of_contents: true --- -{% compatibility 'dart: "1.78.0"', 'libsass: false', 'ruby: false', 'feature: "Color Spaces"' %} - LibSass, Ruby Sass, and older versions of Dart Sass don't support color spaces - other than `rgb` and `hsl`. - - As well as to adding support for new color spaces, this release changed some - details of the way colors were handled. In particular, even the legacy `rgb` - and `hsl` color spaces are no longer clamped to their gamuts; it's now - possible to represent `rgb(500 0 0)` or other out-of-bounds values. In - addition, `rgb` colors are no longer rounded to the nearest integer because - the CSS spec now requires implementations to maintain precision wherever - possible. -{% endcompatibility %} - -{% compatibility 'dart: "1.14.0"', 'libsass: false', 'ruby: "3.6.0"', 'feature: "Level 4 Syntax"' %} +{% compatibility 'dart: "1.14.0"', 'libsass: "3.6.0"', 'ruby: "3.6.0"', 'feature: "Level 4 Syntax"' %} LibSass and older versions of Dart or Ruby Sass don't support [hex colors with an alpha channel][]. [hex colors with an alpha channel]: https://drafts.csswg.org/css-color/#hex-notation {% endcompatibility %} -Sass has built-in support for color values. Just like CSS colors, each color -represents a point in a particular color space such as `rgb` or `lab`. Sass -colors can be written as hex codes (`#f2ece4` or `#b37399aa`), [CSS color names] -(`midnightblue`, `transparent`), or color functions like [`rgb()`], [`lab()`], -or [`color()`]. +Sass has built-in support for color values. Just like CSS colors, they represent +points in the [sRGB color space][], although many Sass [color functions][] +operate using [HSL coordinates][] (which are just another way of expressing sRGB +colors). Sass colors can be written as hex codes (`#f2ece4` or `#b37399aa`), +[CSS color names][] (`midnightblue`, `transparent`), or the functions +[`rgb()`][], [`rgba()`][], [`hsl()`][], and [`hsla()`][]. [sRGB color space]: https://en.wikipedia.org/wiki/SRGB [color functions]: /documentation/modules/color +[HSL coordinates]: https://en.wikipedia.org/wiki/HSL_and_HSV [CSS color names]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords [`rgb()`]: /documentation/modules#rgb -[`lab()`]: /documentation/modules#lab -[`color()`]: /documentation/modules#color +[`rgba()`]: /documentation/modules#rgba +[`hsl()`]: /documentation/modules#hsl +[`hsla()`]: /documentation/modules#hsla {% codeExample 'colors', false %} @debug #f2ece4; // #f2ece4 @debug #b37399aa; // rgba(179, 115, 153, 67%) @debug midnightblue; // #191970 - @debug rgb(204 102 153); // #c69 - @debug lab(32.4% 38.4 -47.7 / 0.7); // lab(32.4% 38.4 -47.7 / 0.7) - @debug color(display-p3 0.597 0.732 0.576); // color(display-p3 0.597 0.732 0.576) + @debug rgb(204, 102, 153); // #c69 + @debug rgba(107, 113, 127, 0.8); // rgba(107, 113, 127, 0.8) + @debug hsl(228, 7%, 86%); // #dadbdf + @debug hsla(20, 20%, 85%, 0.7); // rgb(225, 215, 210, 0.7) === @debug #f2ece4 // #f2ece4 @debug #b37399aa // rgba(179, 115, 153, 67%) @debug midnightblue // #191970 - @debug rgb(204 102 153) // #c69 - @debug lab(32.4% 38.4 -47.7 / 0.7) // lab(32.4% 38.4 -47.7 / 0.7) - @debug color(display-p3 0.597 0.732 0.576) // color(display-p3 0.597 0.732 0.576) + @debug rgb(204, 102, 153) // #c69 + @debug rgba(107, 113, 127, 0.8) // rgba(107, 113, 127, 0.8) + @debug hsl(228, 7%, 86%) // #dadbdf + @debug hsla(20, 20%, 85%, 0.7) // rgb(225, 215, 210, 0.7) {% endcodeExample %} -## Color Spaces - -Sass supports the same set of color spaces as CSS. A Sass color will always be -emitted in the same color space it was written in unless it's in a [legacy color -space] or you convert it to another space using [`color.to-space()`]. All the -other color functions in Sass will always return a color in the same spaces as -the original color, even if the function made changes to that color in another -space. - -[legacy color space]: #legacy-color-spaces -[`color.to-space()`]: /documentation/modules/color#to-space - -Although each color space has bounds on the gamut it expects for its channels, -Sass can represent out-of-gamut values for any color space. This allows a color -from a wide-gamut space to be safely converted into and back out of a -narrow-gamut space without losing information. - -{% headsUp %} - CSS requires that some color functions clip their input channels. For example, - `rgb(500 0 0)` clips its red channel to be within [0, 255] and so is - equivalent to `rgb(255 0 0)` even though `rgb(500 0 0)` is a distinct value - that Sass can represent. You can always use Sass's [`color.change()`] function - to set an out-of-gamut value for any space. - - [`color.change()`]: /documentation/modules/color#change -{% endheadsUp %} - -Following is a full list of all the color spaces Sass supports. You can read -learn about these spaces [on MDN]. - -[on MDN]: https://developer.mozilla.org/en-US/docs/Glossary/Color_space - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SpaceSyntaxChannels [min, max]
rgb* - rgb(102 51 153)
- #663399
- rebeccapurple -
- red [0, 255]; - green [0, 255]; - blue [0, 255] -
hsl*hsl(270 50% 40%) - hue [0, 360]; - saturation [0%, 100%]; - lightness [0%, 100%] -
hwb*hwb(270 20% 40%) - hue [0, 360]; - whiteness [0%, 100%]; - blackness [0%, 100%] -
srgbcolor(srgb 0.4 0.2 0.6) - red [0, 1]; - green [0, 1]; - blue [0, 1] -
srgb-linearcolor(srgb-linear 0.133 0.033 0.319) - red [0, 1]; - green [0, 1]; - blue [0, 1] -
display-p3color(display-p3 0.374 0.21 0.579) - red [0, 1]; - green [0, 1]; - blue [0, 1] -
a98-rgbcolor(a98-rgb 0.358 0.212 0.584) - red [0, 1]; - green [0, 1]; - blue [0, 1] -
prophoto-rgbcolor(prophoto-rgb 0.316 0.191 0.495) - red [0, 1]; - green [0, 1]; - blue [0, 1] -
rec2020color(rec2020 0.305 0.168 0.531) - red [0, 1]; - green [0, 1]; - blue [0, 1] -
xyz, xyz-d65 - color(xyz 0.124 0.075 0.309)
- color(xyz-d65 0.124 0.075 0.309) -
- x [0, 1]; - y [0, 1]; - z [0, 1] -
xyz-d50color(xyz-d50 0.116 0.073 0.233) - x [0, 1]; - y [0, 1]; - z [0, 1] -
lablab(32.4% 38.4 -47.7) - lightness [0%, 100%]; - a [-125, 125]; - b [-125, 125] -
lchlch(32.4% 61.2 308.9deg) - lightness [0%, 100%]; - chroma [0, 150]; - hue [0deg, 360deg] -
oklaboklab(44% 0.088 -0.134) - lightness [0%, 100%]; - a [-0.4, 0.4]; - b [-0.4, 0.4] -
oklchoklch(44% 0.16 303.4deg) - lightness [0%, 100%]; - chroma [0, 0.4]; - hue [0deg, 360deg] -
- -Spaces marked with * are [legacy color spaces]. - -[legacy color spaces]: #legacy-color-spaces - -## Missing Channels - -Colors in CSS and Sass can have "missing channels", which are written `none` and -represent a channel whose value isn't known or doesn't affect the way the color -is rendered. For example, you might write `hsl(none 0% 50%)`, because the hue -doesn't matter if the saturation is `0%`. In most cases, missing channels are -just treated as 0 values, but they do come up occasionally: - -* If you're mixing colors together, either as part of CSS interpolation for - something like an animation or using Sass's [`color.mix()`] function, missing - channels always take on the other color's value for that channel if possible. - - [`color.mix()`]: /documentation/modules/color#mix - -* If you convert a color with a missing channel to another space that has an - analogous channel, that channel will be set to `none` after the conversion is - complete. - -Although [`color.channel()`] will return 0 for missing channels, you can always -check for them using [`color.is-missing()`]. - -[`color.channel()`]: /documentation/modules/color#channel -[`color.is-missing()`]: /documentation/modules/color#is-missing - -{% codeExample 'missing-channels', false %} - @use 'sass:color'; - - $grey: hsl(none 0% 50%); - - @debug color.mix($grey, blue, $method: hsl); // hsl(240, 50%, 50%) - @debug color.to-space($grey, lch); // lch(53.3889647411% 0 none) - === - @use 'sass:color' - - $grey: hsl(none 0% 50%) - - @debug color.mix($grey, blue, $method: hsl) // hsl(240, 50%, 50%) - @debug color.to-space($grey, lch) // lch(53.3889647411% 0 none) -{% endcodeExample %} - -### Powerless Channels - -A color channel is considered "powerless" under certain circumstances its value -doesn't affect the way the color is rendered on screen. The CSS spec requires -that when a color is converted to a new space, any powerless channels are -replaced by `none`. Sass does this in all cases except conversions to legacy -spaces, to guarantee that converting to a legacy space always produces a color -that's compatible with older browsers. - -For more details on powerless channels, see [`color.is-powerless()`]. - -[`color.is-powerless()`]: /documentation/modules/color#is-powerless - -## Legacy Color Spaces - -Historically, CSS and Sass only supported the standard RGB gamut, and only -supported the `rgb`, `hsl`, and `hwb` functions for defining colors. Because at -the time all colors used the same gamut, every color function worked with every -color regardless of its color space. Sass still preserves this behavior, but -only for older functions and only for colors in these three "legacy" color -spaces. Even so, it's still a good practice to explicitly specify the `$space` -you want to work in when using color functions. +{% funFact %} + No matter how a Sass color is originally written, it can be used with both + HSL-based and RGB-based functions! +{% endfunFact %} -Sass will also freely convert between different legacy color spaces when -converting legacy color values to CSS. This is always safe, because they all use -the same underlying color model, and this helps ensure that Sass emits colors in -as compatible a format as possible. +CSS supports many different formats that can all represent the same color: its +name, its hex code, and [functional notation][]. Which format Sass chooses to +compile a color to depends on the color itself, how it was written in the +original stylesheet, and the current output mode. Because it can vary so much, +stylesheet authors shouldn't rely on any particular output format for colors +they write. -## Color Functions +[functional notation]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value -Sass supports many useful [color functions] that can be used to create new -colors based on existing ones by [mixing colors together] or [scaling their -channel values]. When calling color functions, color spaces should always be -written as unquoted strings to match CSS, while channel names should be written -as quoted strings so that channels like `"red"` aren't parsed as color values. +Sass supports many useful [color functions][] that can be used to create new +colors based on existing ones by [mixing colors together][] or [scaling their +hue, saturation, or lightness][]. [mixing colors together]: /documentation/modules/color#mix -[scaling their channel values]: /documentation/modules/color#scale - -{% funFact %} - Sass color functions can automatically convert colors between spaces, which - makes it easy to do transformations in perceptually-uniform color spaces like - Oklch. But they'll *always* return a color in the same space you gave it, - unless you explicitly call [`color.to-space()`] to convert it. - - [`color.to-space()`]: /documentation/modules/color#to-space -{% endfunFact %} +[scaling their hue, saturation, or lightness]: /documentation/modules/color#scale {% codeExample 'color-formats', false %} - @use 'sass:color'; - $venus: #998099; - @debug color.scale($venus, $lightness: +15%, $space: oklch); - // rgb(170.1523703626, 144.612080603, 170.1172627174) - @debug color.mix($venus, midnightblue, $method: oklch); - // rgb(95.9363315581, 74.5687109346, 133.2082569526) + @debug scale-color($venus, $lightness: +15%); // #a893a8 + @debug mix($venus, midnightblue); // #594d85 === - @use 'sass:color' - $venus: #998099 - @debug color.scale($venus, $lightness: +15%, $space: oklch) - // rgb(170.1523703626, 144.612080603, 170.1172627174) - @debug color.mix($venus, midnightblue, $method: oklch) - // rgb(95.9363315581, 74.5687109346, 133.2082569526) + @debug scale-color($venus, $lightness: +15%) // #a893a8 + @debug mix($venus, midnightblue) // #594d85 {% endcodeExample %}