Re: [csswg-drafts] [css-values-5] Add `spread()` to CSS (#8391)

I agree that there's a need for something in this vein, to allow storing arglists for functions like `random-item()` (and other semicolon-delimited lists) in a variable. Not a fan of exactly how it's proposed here, tho - it runs into some awkward grammar issues.

The core issue here is that a function can take `<any-value>`, while properties are limited to `<declaration-value>`. To store an `<any-value>` in a property, you need *something* to wrap it so it's not top-level; then you need some way to discard the wrapper when it's actually used (but not before then - if you sub a var() into another custom prop, it needs to retain the wrapper so the value remains valid).

So I think there are two possible approaches:

1. Define a function, call it `spread1()`, that is valid as a whole argument in `random-item()` and any other functions that accept anything broader than `<declaration-value>`. It has the grammar `spread(<any-value>)` (and thus can contain itself). Its only effect is to discard itself at computed-value time, lifting its own arguments into the parent function.
 
 If used anywhere else it's just invalid syntax. Custom properties using `*` grammar can of course use it, since they just see a token stream rather than a function.

2. Define a function, call it `spread2()`, that isn't valid *anywhere* - only the `*` grammar can use it. It has special substitution behavior: 
 * if subbed into another `*` grammar, it subs as-is
 * if subbed into anything else, it discards itself and leaves its argument behind.

The two are basically identical in usage:

```css
.foo {
  --multiple-items: spread(1; 2; 3; 4; 5);
  --single-item: 6;
  some-prop: random-item(--x; var(--multiple-items); var(--single-item));
  /* equivalent to */
  some-prop: random-item(--x; 1; 2; 3; 4; 5; 6);
}

/* and nesting them works */
.foo {
  --some-items: spread(1; 2; 3);
  --more-items: spread(var(--some-items); 4; 5; 6);
  --some-prop: random-item(--x; var(--more-items));
}
```

There are only meaningful difference between the two approaches is whether they're allowed in places that don't *require* them - `spread1()` isn't (it's defined to only be valid in the functions that need it) while `spread2()` is (can be used anywhere, but doesn't add any ability). Having the function be invalid where it's not needed (as in `spread1()`) might be good at discouraging confusing overuse, but having it be more explicitly tied to variable substitution (as in `spread2()`) might also be good for understanding. Really not sure which side I prefer.

-- 
GitHub Notification of comment by tabatkins
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/8391#issuecomment-1414225090 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Thursday, 2 February 2023 19:04:58 UTC