Skip to content

[css-values-5][various] Better handling of arguments with commas #9539

Closed
@tabatkins

Description

We've got several in-flight proposals for functions that can take "whole property value" arguments, like mix(), random-item(), etc. (And now custom functions and mixins, which @mirisuzanne and I are looking into more seriously again.) Because these arguments can potentially contain commas (say, mixing between two background-image lists), we can't use commas as the argument separator, and the proposals currently all use semicolons as the separator instead, as this is guaranteed to never show up at the top-level of a property value.

Even tho I'm the one that started this trend, I don't like it. ^_^ I'd like to find a different solution. The problems are:

  • It's obviously a bit inconsistent with existing functions. It's not terrible, but it's not good either.
  • A lot of userland tools use very simplistic parsers, and divide properties by just splitting on semicolons. This'll break them until they rewrite to be aware of nesting levels for matched parens.
  • Most uses of these functions don't need the special separator; it's only the rare uses that involve operating on an entire comma-separated list that do. Forcing people to do a weird thing for a case they'll rarely hit isn't great.
  • It's not forward-compatible in some cases. We have to design this syntax into the function right from the beginning, and can't ever expand an existing comma-separated function into it (unless we do a grammar split, which is nasty in its own way).
  • The var() function already lets you take this kind of argument, but because its syntax was designed to take only one, and as the final argument, it can continue to use comma separation. (That is, you can write var(--foo, blue, red, black) - that's two args, a -foo and a blue, red, black list.)

The obvious solution is to add an optional wrapper around arguments, which will "hide" the commas from the outer function. It would only be necessary when someone is actually passing a comma-separated argument.

I have two possible suggestions, and am happy with either:

  • Use [], like background: mix(50%, url(start), [ url(foo), url(bar) ]);
  • Use a new, generically named function, like item(): background: mix(50%, url(start), item( url(foo), url(bar) ));

This notation would only be allowed in the functions that can take these problematic values, and if present, would be stripped for the purpose of the actual value. No nesting - if you were mixing a subgridded "line names only" value for grid-template-columns, for example, you'd write it as grid-template-columns: mix(50%, [[foo bar]], [[baz qux]]), so the outer [] gets stripped and the inner [] is part of the actual value.

(I'm rejecting using naked () for the same reason we ended up switching away from them for grid lines - it would mess up Sass syntax, and possibly others, hardcore, since in Sass it indicates math. I'm rejecting {} for "naive userland tools" reasons; again, many just split the text with regexes, and stray {} can screw them up. They're already potentially broken for custom props containing these chars, of course, but that's not an official Part Of CSS like this would be.)

Thoughts?

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    • Status

      Unsorted regular
    • Status

      Thursday morning

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions