Add/update strict function unit documentation (#683)

This merges the color-units and random-with-units deprecation pages
into a single shared function-units page, updates the color-units
deprecations to reflect that Phase 2 has been enacted, and adds new
function unit deprecations.

See #511
See sass/sass#2904
See #662
See sass/sass#3374
This commit is contained in:
Natalie Weizenbaum 2022-10-28 16:35:58 -07:00 committed by GitHub
parent 079e1237ae
commit f80aa04469
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 217 additions and 122 deletions

View File

@ -71,6 +71,11 @@ Dir['source/documentation/breaking-changes/**'].each do |file|
redirect "d/#{basename}.html", to: "/documentation/breaking-changes/#{basename}"
end
for url in %w[d/random-with-units documentation/breaking-changes/random-with-units
d/breaking-changes/color-units documentation/breaking-changes/color-units] do
redirect url, to: "/documentation/breaking-changes/function-units"
end
redirect 'tutorial.html', to: '/guide'
redirect 'download.html', to: '/install'
redirect 'try.html', to: 'https://www.sassmeister.com'

View File

@ -23,18 +23,15 @@ time-sensitive, so they may be released with new minor version numbers instead.
These breaking changes are coming soon or have recently been released:
* [`random()` with units](breaking-changes/random-with-units) beginning in Dart
Sass 1.54.5.
* [Functions are stricter about which units they
allow](breaking-changes/function-units) beginning in Dart Sass 1.32.0.
* [Selectors with invalid combinators will be
* [Selectors with invalid combinators are
invalid](breaking-changes/bogus-combinators) beginning in Dart Sass 1.54.0.
* [`/` is changing from a division operation to a list
separator](breaking-changes/slash-div) beginning in Dart Sass 1.33.0.
* [Color functions are becoming more strict about
units](breaking-changes/color-units) beginning in Dart Sass 1.32.0.
* [Parsing the special syntax of `@-moz-document` will be
invalid](breaking-changes/moz-document) beginning in Dart Sass 1.7.2.

View File

@ -1,79 +0,0 @@
---
title: "Breaking Change: Color Units"
introduction: >
In CSS, saturation and lightness parameters always require `%` units and hue
parameters allow any angle unit. Sass has historically ignored units for these
functions. We're in the process of changing that.
---
It's important that we keep Sass's implementation of [`hsl()`] consistent with
the CSS spec, and that we keep other Sass functions that deal with colors
consistent with `hsl()`. One notable place where Sass has historically differed
from the spec is the way that `hsl()` (and other color functions) handled units.
[`hsl()`]: ../modules#hsl
For hue, CSS allows any [angle unit][] (`deg`, `grad`, `rad`, or `turn`). It
also allows a unitless number, which is interpreted as `deg`. Historically, Sass
has allowed *any* unit, and interpreted it as `deg`. This is particularly
problematic because it meant that the valid CSS expression `hsl(0.5turn, 100%,
50%)` would be allowed by Sass but interpreted entirely wrong.
[angle unit]: https://drafts.csswg.org/css-values-4/#angles
For lightness and saturation, CSS only allows `%` units. Even unitless numbers
aren't allowed (unlike for the hue). Historically, Sass has allowed *any* unit,
and interpreted it as `%`. You could even write `hsl(0, 100px, 50s)` and Sass
would return the color `red`.
To fix this issue and bring Sass in line with the CSS spec, we're making changes
in multiple phases:
## Phase 1
<% impl_status dart: '1.32.0', libsass: false, ruby: false %>
To begin with, we're just introducing deprecation warnings for behaviors that we
plan to change. Specifically, Sass will emit a deprecation warning if you do any
of the following:
* Pass a number with a unit other than `deg` as a hue to any function. Passing a
unitless number is still allowed.
* Pass a unitless number as saturation or lightness to any function.
* Pass a number with a unit other than `%` as saturation or lightness to any
function.
Of these warnings, the first is the most important one to deal with immediately
specifically if you're passing a number with unit `grad`, `rad`, or `turn`. This
case will change behavior in Phase 2, which could change how your stylesheets
render if you don't update them.
## Phase 2
<% impl_status dart: false, libsass: false, ruby: false %>
At least three months after the launch of Phase 1, we'll change the way angle
units are handled for hue parameters to match the CSS spec. This means that
numbers with `grad`, `rad`, or `turn` units will be converted to `deg`:
`0.5turn` will be converted to `180deg`, `100grad` will be converted to `90deg`,
and so on.
Because this change is necessary to preserve CSS compatibility, according to the
[Dart Sass compatibility policy] it will be made with only a minor version bump.
However, it changes as little behavior as possible to ensure that Sass
interprets all valid CSS according to the CSS spec. All other deprecated
behavior will remain in place until Phase 3.
[Dart Sass compatibility policy]: https://github.com/sass/dart-sass#compatibility-policy
## Phase 3
<% impl_status dart: false, libsass: false, ruby: false %>
Finally, we'll remove all deprecated behavior by making color functions throw
errors if they're passed any units that produced deprecation warnings in Phase
1. Because this is a breaking change that's not strictly necessary for CSS
compatibility, we'll land it as part of Dart Sass 2.0.0 (which we have no
immediate plans to release).

View File

@ -0,0 +1,209 @@
---
title: "Breaking Change: Strict Function Units"
introduction: >
Various built-in functions will become stricter in which units they allow
and will handle those units more consistently. This makes Sass more compatible
with the CSS spec and helps catch errors more quickly.
---
## Hue
<% impl_status dart: '1.32.0', libsass: false, ruby: false %>
When specifying a color's hue, CSS allows any [angle unit][] (`deg`, `grad`,
`rad`, or `turn`). It also allows a unitless number, which is interpreted as
`deg`. Historically, Sass has allowed *any* unit, and interpreted it as `deg`.
This is particularly problematic because it meant that the valid CSS expression
`hsl(0.5turn, 100%, 50%)` would be allowed by Sass but interpreted entirely
wrong.
[angle unit]: https://drafts.csswg.org/css-values-4/#angles
To fix this issue and bring Sass in line with the CSS spec, we're making changes
in multiple phases:
### Phase 1
<% impl_status dart: '1.32.0', libsass: false, ruby: false %>
At first, Sass just emitted a deprecation warning if you passed a number with a
unit other than `deg` as a hue to any function. Passing a unitless number is
still allowed.
### Phase 2
<% impl_status dart: '1.52.1', libsass: false, ruby: false %>
Next, we changed the way angle units are handled for hue parameters to match the
CSS spec. This means that numbers with `grad`, `rad`, or `turn` units will be
converted to `deg`: `0.5turn` will be converted to `180deg`, `100grad` will be
converted to `90deg`, and so on.
Because this change is necessary to preserve CSS compatibility, according to the
[Dart Sass compatibility policy] it was made with only a minor version bump.
However, it changes as little behavior as possible to ensure that Sass
interprets all valid CSS according to the CSS spec.
[Dart Sass compatibility policy]: https://github.com/sass/dart-sass#compatibility-policy
### Phase 3
<% impl_status dart: false, libsass: false, ruby: false %>
Finally, in Dart Sass 2.0.0 color functions will throw errors if they're passed
a hue parameter with a non-angle unit. Unitless hues will still be allowed.
## Saturation and Lightness
When specifying an HSL color's saturation and lightness, CSS only allows `%`
units. Even unitless numbers aren't allowed (unlike for the hue). Historically,
Sass has allowed *any* unit, and interpreted it as `%`. You could even write
`hsl(0, 100px, 50s)` and Sass would return the color `red`.
To fix this issue and bring Sass in line with the CSS spec, we're making changes
in two phases:
### Phase 1
<% impl_status dart: '1.32.0', libsass: false, ruby: false %>
Currently, Sass just emits a deprecation warning if you pass a number with no
unit or a unit other than `%` as a lightness or saturation to any function.
### Phase 2
<% impl_status dart: false, libsass: false, ruby: false %>
In Dart Sass 2.0.0 color functions will throw errors if they're passed a
saturation or lightness parameter with no unit or a non-`%` unit.
## Alpha
When specifying a color's alpha value, CSS (as of [Colors Level 4]) allows
either unitless values between 0 and 1 or `%` values between `0%` and `100%`. In
most cases Sass follows this behavior, but the functions `color.adjust()` and
`color.change()` have historically allowed *any* unit, and interpreted it as
unitless. You could even write `color.change(red, $alpha: 1%)` and Sass would
return the opaque color `black`.
[Colors Level 4]: https://www.w3.org/TR/css-color-4/#typedef-alpha-value
To fix this issue and bring Sass in line with the CSS spec, we're making changes
in three phases:
### Phase 1
<% impl_status dart: '1.56.0', libsass: false, ruby: false %>
Currently, Sass just emits a deprecation warning if you pass a number with any
unit, including `%`, as an alpha value to `color.change()` or `color.adjust()`.
### Phase 2
<% impl_status dart: false, libsass: false, ruby: false %>
Next, we'll change the way `%` units are handled for the alpha argument to
`color.change()` and `color.adjust()`. Alphas with unit `%` will be divided by
`100%`, converting them to unitless numbers between 0 and 1.
Because this change is a bug fix that improves consistency with other Sass
functions, it will be made with only a minor version bump. It will be changed at
minimum three months after Phase 1 is released, to give users time to adjust
their code and avoid the bug.
[Dart Sass compatibility policy]: https://github.com/sass/dart-sass#compatibility-policy
### Phase 3
<% impl_status dart: false, libsass: false, ruby: false %>
Finally, in Dart Sass 2.0.0 `color.change()` and `color.adjust()` will throw
errors if they're passed an alpha parameter with a non-`%` unit. Unitless alphas
will still be allowed.
## `math.random()`
[The `math.random()` function] has historically ignored units in `$limit` and
returned a unitless value. For example `math.random(100px)` would drop "px" and
return a value like `42`.
A future version of Sass will stop ignoring units for the `$limit` argument and
return a random integer with the same units.
[The `math.random()` function]: ../modules/math#random
<% example(autogen_css: false) do %>
// Future Sass, doesn't work yet!
@debug math.random(100px); // 42px
===
// Future Sass, doesn't work yet!
@debug math.random(100px) // 42px
<% end %>
### Phase 1
<% impl_status dart: '1.54.5', libsass: false, ruby: false %>
Currently, Sass emits a deprecation warning if you pass a `$limit` with units to
`math.random()`.
### Phase 2
<% impl_status dart: false, libsass: false, ruby: false %>
In Dart Sass 2.0.0, passing a `$limit` number with units will be an error.
### Phase 3
<% impl_status dart: false, libsass: false, ruby: false %>
In a minor release after Dart Sass 2.0.0, passing a `$limit` number with units
to the `math.random()` function will be allowed again. It will return a random
integer the same units as `$limit`, instead of a unitless number.
## Weight
The [`color.mix()` function] and [`color.invert()` function] have both
historically ignored units in their `$weight` arguments, despite that argument
conceptually representing a percentage. A future version of Sass will require
the unit `%`.
[`color.mix()` function]: ../modules/color#mix
[`color.invert()` function]: ../modules/color#invert
### Phase 1
<% impl_status dart: '1.56.0', libsass: false, ruby: false %>
Currently, Sass emits a deprecation warning if you pass a `$weight` with no
units or with units other than `%` to `color.mix()` or `color.invert()`.
### Phase 2
<% impl_status dart: false, libsass: false, ruby: false %>
In Dart Sass 2.0.0, `color.mix()` and `color.invert()` will throw errors if
they're passed a `$weight` with no unit or a non-`%` unit.
## Index
The [`list.nth()` function] and [`list.set-nth()` function] have both
historically ignored units in their `$n` arguments. A future version of Sass
will forbid any units.
[`list.nth()` function]: ../modules/list#nth
[`list.set-nth()` function]: ../modules/list#set-nth
### Phase 1
<% impl_status dart: '1.56.0', libsass: false, ruby: false %>
Currently, Sass emits a deprecation warning if you pass a `$weight` with no
units or with units other than `%` to `color.mix()` or `color.invert()`.
### Phase 2
<% impl_status dart: false, libsass: false, ruby: false %>
In Dart Sass 2.0.0, `list.nth()` and `list.set-nth()` will throw errors if
they're passed an index `$n` with a unit.

View File

@ -1,37 +0,0 @@
---
title: "Breaking Change: Random With Units"
introduction: >
The `random()` function will no longer ignore units on the `$limit` argument
in a future version. Passing a `$limit` with units is deprecated to ensure the
compilation results don't change once the new behavior lands.
---
[The `random()` function] has historically ignored units in `$limit` and
returned a unitless value. For example `random(100px)` would drop "px" and
return a value like `42`.
A future implementation of Dart Sass will stop ignoring units for the `$limit`
argument and return a random integer with the same units.
[The `random()` function]: ../modules/math#random
<% example(autogen_css: false) do %>
// Future Sass, doesn't work yet!
@debug math.random(100px); // 42px
===
// Future Sass, doesn't work yet!
@debug math.random(100px) // 42px
<% end %>
## Transition Period
<% impl_status dart: '1.54.5', libsass: false, ruby: false %>
First, the Sass compiler will emit a deprecation warning for previous uses of
`random()` when the `$limit` argument has units. The warning will suggest a way
to preserve the existing behavior and another way that emulates the future
implementation.
In Dart 2.0.0 passing a `$limit` number with units will be an error, and then in
a future minor release the `random()` function will return a random integer the
same units as `$limit`.