Skip to content

Stop using / as division #2565

@nex3

Description

@nex3

The current plan:

  1. Create an automated migration tool that can migrate users from /-as-division to a divide() function.
  2. Deprecate /-as-division. Any time a / would be interpreted unambiguously as division, or an ambiguous / would be made unambiguous (for example by being stored in a variable), we produce a deprecation warning .
  3. Add a top-level divide() function (math.div() in the new module system). This will work exactly the same way division works today, with the obvious exception that it will never be treated as a slash separator.
  4. Add a new slash-separated list type to represent slash as a separator. For the time being, this will not have a literal syntax.
  5. Add a slash-list() function (list.slash() in the new module system) that returns a slash-separated list. Providing the ability to work with slash-separated lists even before they have a literal syntax will help stylesheets be forwards-compatible with the new wold.
  6. Wait until at least three months after the module system is released.
  7. Release Dart Sass 2.0.0, which parses / as a list separator that binds more loosely than space but more tightly than comma.
  8. Add support for first class calc(), which will allow /-as-division in the form of calc(5px / 2).
  9. Deprecate the slash-list()/list.slash() function in favor of using the literal syntax.
  10. Whenever Dart Sass 3.0.0 releases, remove slash-list() and list.slash().

The original issue:

When Sass was first designed, the most prominent use of / as a separator in CSS was the short-form font property, which used it to separate values for font-size and line-height. Because this was a relatively narrow edge case, we were able to use / as the division operator as well, with some heuristics to decide between them. When / was used as a separator, the value it produced was actually the divided number, but it was rendered with the slash instead.

However, the slash separator has been seeing more use in recent CSS specs. The grid-row property uses it to separate values for grid-row-start and grid-row-end, and Colors Level 4 uses it in many color functions (including the new recommended syntax for rgb() and hsl()) to separate the alpha value from the rest of the parameters.

The increased prominence of this syntax means that the sharp edges of the heuristics we use to distinguish between /-as-separator and /-as-division will start cutting more users. Once Sass supports the new color function syntax (#2564), users are likely to try passing the alpha by variable, which will currently fail. We need to decide whether to do something about this, and if so, what.

How do we represent division?

Today, division is represented by the operator /, which as discussed above is ambiguous. We could fairly easily add a new syntax for this, which would allow us to migrate users away from /, eventually leaving it as unambiguously a separator.

I see a few options for this:

  • Keep the behavior as-is. This has the substantial benefit of requiring no migration, and it will be sufficient to support compatibility with plain CSS. However, it will make it much more painful for users to use dynamic alpha values for their colors as the new color function syntax gains traction.

  • Replace the / operator with another operator. There's no option that's really consistent with other programming languages, but ~ is a possibility that's currently unused and looks a little like ÷.
    Stop using / as division #2565

  • Replace the / operator with a function, such as div(). This is more verbose, but it's very clear to the reader and it avoids any risk of further collision with new CSS syntax.

What is a slash separator?

If we do decide to free up / to unambiguously represent a separator, we need to figure out how that separator works in terms of SassScript. This is particularly tricky because its scope varies from property to property. In font, it's tightly bound--the slash in italic small-caps bold 16px/2 cursive separates 16px from 2, but it doesn't separate italic small-caps bold 16px from 2 cursive. However, in grid-row and the color functions, it's loosely bound--the slash in rgb(1 2 3 / 0.5) separates 1 2 3 from 0.5, and is not bound to 3 in particular.

I think it makes sense in general to consider / another kind of list separator, so that it works smoothly with existing APIs. But because of the scoping differences it's not clear whether it should bind more tightly than space-separated lists or not. That is, should 1 2 / 3 4 be equivalent to (1 2) / (3 4) or 1 (2 / 3) 4?

Metadata

Metadata

Assignees

No one assigned

    Labels

    CSS compatibilitySupport the CSS specplannedWe would like to add this feature at some pointrequires deprecationBlocked on a deprecation cycle

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions