[csswg-drafts] [css-properties-values-api] A compact syntax for registering global constants/custom properties (#9206)

mirisuzanne has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-properties-values-api] A compact syntax for registering global constants/custom properties ==
There has been discussion in several issues recently about providing a `::document` selector, or `@document`/`@global`/`@env` rule that would allow authors a quick way to register globally available constants (as custom properties or environment variables)  - without a full `@property` rule describing each individually. See, for example:

- https://github.com/w3c/csswg-drafts/issues/6931
- https://github.com/w3c/csswg-drafts/issues/6641
- https://github.com/w3c/csswg-drafts/issues/2627

(Hopefully this issue is useful as a way of combining several discussions, and not just a duplicate)

Those first two issues have more specific concerns that could be (or have been) addressed in specific ways - but mention the possibility we might still want a more generic solution for registering global properties. [Custom media queries](https://www.w3.org/TR/mediaqueries-5/#custom-mq) (`@custom-media`) have similarly been solved as a specific case, but not yet implemented – and there's an open issue for adding [`@custom-container`](https://github.com/w3c/csswg-drafts/issues/8121). Those use-cases could also be solved by a well-defined global parameter registry.

There are two primary overlapping concerns here:

- A less verbose syntax for authors to register custom properties with an initial value and syntax. As @LeaVerou [has pointed out](https://github.com/w3c/csswg-drafts/issues/6931#issuecomment-1030429039), authors define _a lot of variables_, and the `@property` rule is a very bulky way to register them one-at-a-time.
- Authors would like to define global values that can be reused in at-rules, or other places where the cascading `var()` would not be possible to resolve.

I tend to [agree with @tabatkins](https://github.com/w3c/csswg-drafts/issues/6641#issuecomment-1006172908) that:

> Having an author-defined `env()` might work, but would require an author to duplicate values across properties and `env()`, or else decide for each whether they want to express it as a var or an `env()`.

I like the proposed solution of allowing global reference to the initial values of registered custom properties, but think we need to make that registration simpler for it to work. I don't know the right syntax for that, but if we're able to come up with something compact, it could also be useful for defining parameters in [declarative custom functions](https://github.com/w3c/csswg-drafts/issues/7490) and (someday, maybe) mixins.

The `@property` rule can register a custom property `name` with three associated descriptors:

- `syntax`: the CSS type/grammar(s) used to validate and interpolate values (often but not always a single type like "<color>" or "<length>"'
- `inherits`: a boolean to set if the property inherits or not (this would not be needed in function/mixin parameters)
- `initial-value`: the initial value of the property

Authors often skip this registration for most properties, and only define the `name` along with an un-registered not-technically-'initial' value on the root element. Then some authors add the `@property` registration for specific properties - often to define a `syntax` for the sake of interpolation, but occasionally to set inheritance or a more formal initial value.

Things I would expect from a syntax:

- Register just the name and initial value (default to universal syntax, with inheritance on)
- Register props with the initial guaranteed invalid value
- Register groups of properties that share a `syntax`
- Register 

The main complexity that I see with defining a compact syntax is that custom property values (including initial values) are very permissive. It will be difficult to combine `initial-value` with anything else on the right side of a standard `property:value;` format – though it should be possible using either the `!` delim-token, or wrapping `()`/`{}`/`[]` of some kind. The other thought I had was to put some of the definition on the left side. Some rough ideas:


```css
@global {
  --my-color("<color>"): mediumvioletred;
  --my-padding("<length>"): 10px !no-inherit;
}

@global "<color>" no-inherit {
  --brand-color: teal;
}
```

The an all-in-one syntax is more appropriate for reuse in function parameter definitions, while the grouped syntax helps with defining a whole set of related variables in a single place.

On the other end, when calling custom properties, a `env()` or `global()` function could give access to the initial registered value anywhere in the document, while `var()` returns only the cascaded value. I prefer this to a context-dependent resolution of `var()`, since it provides more clarity on what value to expect, and makes both available where `var()` is already supported:

```css
.my-thing {
  color: var(--brand-color);
  padding: global(--my-padding);

  @media global(--above-small) {
    ...
  }
}
```

This is far from a complete proposal, and mostly a request that we consider these use-cases together. Happy for thoughts, and willing to merge this into the `env()` conversation if it belongs there. 

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/9206 using your GitHub account


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

Received on Thursday, 17 August 2023 17:57:56 UTC