Open kizu opened 4 years ago
I seem to recall that, for the JS syntax, there was an explicit choice to make inherits
required, because it is unusual in JavaScript to have a missing object property treated as true
by default. I don't entirely agree with it, but I understand the argument. I certainly agree that is unnecessarily verbose for the CSS syntax.
I also agree that initial-value
and syntax
should be optional (for both CSS and JS methods of registering properties), with the defaults Roma suggests.
In particular, it is very useful to support syntax
without initial-value
, to allow transitions/animations while also supporting fallbacks in the var()
function for when the variable has not been set.
(This brings up another question: should there be an explicit way to indicate that the initial value is the guaranteed-invalid value, maybe initial-value: initial
? But at the very least, it should be possible to preserve this behavior by not setting an initial value.)
All of these are required for good reasons. ^_^
As Amelia said, making inherits
required is very intentional, to force authors to think about it. Inherited properties are more expensive than non-inherited, and given a choice, we probably shouldn't be defaulting to the more expensive option. Also, yes, having bools default to true
is weird in JS and we should avoid it whenever possible.
Similarly, syntax
is required because the "*"
grammar is not very useful. We need "*"
so we can support arbitrary values, but it's much better for us to guide authors to supplying a meaningful syntax
that we can actually transition/etc when possible. If they don't need it, syntax:"*",
is really short to type anyway.
And finally, initialValue
is required whenever syntax
isn't "*"
because the guaranteed-invalid value doesn't match any specific syntax at all. We want to ensure that, if you say a custom property is a "<color>"
, you get a color when you query that property.
I'm open to allowing the guaranteed-invalid value as part of a custom property's value space; there's nothing wrong with syntax: "<color> | <guaranteed-invalid>"
. But I don't think it's good to make it easy to include it in your value space by default; I'd rather guide people (via the "missing key" errors) to set up their value space properly.
Well, I disagree that making the syntax more verbose to force authors think is a good idea.
If the intent was for authors to use non-inherited variables more — the default should have been false
then (I personally would be all for it). Though, I guess, this is one thing that could potentially backfire: I imagine most authors would want to use property registration for transitions after they would already have some code, which could depend on inheritance. But, yes, I don't see anything bad in having a positive value for default, and explicitly disabling inheritance when needed.
But making authors write more when there is no real need is just an invitation for someone to come-up with shortcuts and extra build/runtime JS that would just do this. Add to this the possibility of a human error, where a typo in a “required, but not needed” part would end in everything not working. And — what are other places in CSS where there are required declarations like that?
Overall, I strongly do not like the idea of guiding authors as if they were blind puppies — especially for this kinds of advanced features. It is awesome that we have them, but sometimes the “good intentions” can make the feature much harder to use than it should have been. We need to have more faith in developers, and if we want to enforce good practices, it is the tools like browsers and code editors that could be used. Browsers could add profiling for the CSS variables performance and suggest not inheriting them (maybe it could be also detected automatically — if the inheritance is never used for a certain custom property, for example).
But maiming the syntax just so developers “would know better”?
Requiring explicitness when there's not an obviously correct-most-of-the-time (or at least obvious-most-of-the-time) default choice is a pretty standard language design pattern. Pretending that it's insulting to authors is incorrect and not helpful to this discussion.
Why have defaults anywhere then? Why gradients have a default direction? Borders — default thickness? backgrounds — default repeat? And so on? Or these were CSS design mistakes and if these would be designed today it would be different?
What are other places in CSS that require explicitness, especially on the level of whole declarations? And not just one required declaration — the need to have four different ones, without a shorthand, just to enable any of these declarations?
Right now custom properties registration can be used for these features:
These features are not connected, but we can't use any one of them without explicitly mentioning the others. In my this coupling is unnecessary and introduces an extra barrier for usage of any of these, and an extra potential for a mistake or a type, where a mistake in one declaration makes the whole thing incorrect, which kinda goes against what CSS is currently is.
Why have defaults anywhere then?
Because API design is a complex and nuanced process, and no approach is correct 100% of the time.
and an extra potential for a mistake or a typo, where a mistake in one declaration makes the whole thing incorrect, which kinda goes against what CSS is currently is.
No, that sort of thing does occur at times in CSS. For example, @counter-style requires a 'system' descriptor, and either 'symbols' or 'additive-symbols', even tho we could theoretically default 'system' to, say, cyclic
. The 'font' shorthand requires you to specify a font-family, even tho we could theoretically default it to serif
(the initial value). Etc.
These are also longhand. And we can say font-size: 3rem
without mentioning the font-family, when we want for it to fallback to inherited/default one. Same with most other shorthands — most would just work when you would provide just the crucial ones.
But when registering property we cannot do this and need to mention all of them even for smaller cases.
The CSS Working Group just discussed make P&V API descriptors optional
, and agreed to the following:
RESOLVED: keep all fields in @property required
Why have defaults anywhere then?
Because API design is a complex and nuanced process, and no approach is correct 100% of the time.
Come on folks, let's not pretend that inherits
is required for API design purposes. That implies that there is a usability reason for this, which is false. If usability was the only factor, inherits
would be optional and would default to true
, because this is the default for non-registered properties. The reason it's required is performance, and thus, is a case of implementation affecting UI decisions, which is actually a usability anti-pattern, not to mention a violation of the Priority of Constituencies ("users before implementors").
I do understand the reasons, and I'm not saying we should make it optional, but telling @kizu that this is done for API design purposes is disingenuous. It's done to discourage use of a value that is performance intensive, plain as that.
I'm open to allowing the guaranteed-invalid value as part of a custom property's value space; there's nothing wrong with
syntax: "<color> | <guaranteed-invalid>"
. But I don't think it's good to make it easy to include it in your value space by default; I'd rather guide people (via the "missing key" errors) to set up their value space properly.
@tabatkins – That would be great! If that was supported, I'm guessing setting such a custom property to something that is not a <color>
would make it guaranteed-invalid instead of reverting to its defined initial-value
? (Also see my comment here – it's possible I'm misunderstanding.)
https://drafts.css-houdini.org/css-properties-values-api-1/
For convenience I would talk about the CSS syntax, but the same could apply to the
registerProperty()
JS function as well.Currently, all the declarations inside the
@property
are required (https://drafts.css-houdini.org/css-properties-values-api-1/#at-property-rule), (with the exception ofinitial-value
, but only for universal syntax definition (*
).My suggestion: make all declarations optional, and if at least one descriptor is properly defined, the custom property should become registered.
Basically, each
descriptor
could have a “default”:syntax
should default to the universal syntax definition. This would allow to conveniently set a variable to be non-inherited without explicitly typing it or setting an initial value.inherits
should default totrue
, as this is the default for unregistered properties. There is no reason to require this descriptor to be explicitly required, and making it optional would allow to use the@property
to more conveniently register properties that could be transitioned.initial-value
should default to… not sure how it can be described, but basically, an “invalid” value. If the syntax is properly defined, then the property should still be able to be transitioned/animated, just both states should be defined, without a transition to or from the “invalid” value.Overall, making all these optional would make the API much easier to use and would reduce potential human errors when registering the custom properties, and would lead to a more readable code overall, as for a lot of cases the property definitions would be more concise and containing only the things developers want to explicitly set.