Repository navigation
[css-values-4][Editorial] <condition> type that other specs reference #10457
Description
This came up when I went to implement the resolution from #10064 and spec my if() proposal.
Currently, we have several specs using one or more types of conditionals, and in every case, this is defined inline. This means the boolean operators (and, or, not) are also defined inline, which is awkward, error-prone, and easy to forget.
Some examples:
<media-query> = <media-condition>
| [ not | only ]? <media-type> [ and <media-condition-without-or> ]?
<media-type> = <ident>
<media-condition> = <media-not> | <media-in-parens> [ <media-and>* | <media-or>* ]
<media-condition-without-or> = <media-not> | <media-in-parens> <media-and>*
<media-not> = not <media-in-parens>
<media-and> = and <media-in-parens>
<media-or> = or <media-in-parens>
<media-in-parens> = ( <media-condition> ) | <media-feature> | <general-enclosed>
<supports-condition> = not <supports-in-parens>
| <supports-in-parens> [ and <supports-in-parens> ]*
| <supports-in-parens> [ or <supports-in-parens> ]*
<supports-in-parens> = ( <supports-condition> ) | <supports-feature> | <general-enclosed>
<supports-feature> = <supports-decl>
<supports-decl> = ( <declaration> )
<supports-feature> = <supports-selector-fn> | <supports-decl>
<supports-selector-fn> = selector( <complex-selector> )
<supports-feature> = <supports-selector-fn> | <supports-font-tech-fn>
| <supports-font-format-fn> | <supports-decl>
<supports-font-tech-fn> = font-tech( <font-tech> )
<supports-font-format-fn> = font-format( <font-format> )
<container-condition> = [ <container-name> ]? <container-query>
<container-name> = <custom-ident>
<container-query> = not <query-in-parens>
| <query-in-parens> [ [ and <query-in-parens> ]* | [ or <query-in-parens> ]* ]
<query-in-parens> = ( <container-query> )
| ( <size-feature> )
| style( <style-query> )
| <general-enclosed>
<style-query> = not <style-in-parens>
| <style-in-parens> [ [ and <style-in-parens> ]* | [ or <style-in-parens> ]* ]
| <style-feature>
<style-in-parens> = ( <style-query> )
| ( <style-feature> )
| <general-enclosed>
<import-conditions> = [ supports( [ <supports-condition> | <declaration> ] ) ]?
<media-query-list>?
media() = media( [ <mf-plain> | <mf-boolean> | <mf-range> ] )
supports() = supports( <declaration> )
In fact, there is an inline issue right there proposing a lighter form of what I’m arguing for here:
Define "boolean algebra, with X as leaves" in a generic way in Conditional, so all the conditional rules can reference it directly, rather than having to redefine boolean algebra on their own.
Proposal
I propose we introduce a new <boolean> or <condition> value type that other specs can reference.
It will include both the grammar for the boolean algebra, as well as bare and functional forms for each conditional.
Each conditional type should also include metadata like:
- Can it change over the course
Not all condition types need to be defined in values, we could extend the <condition> token in other specs, as we often do with value types. E.g. size queries may be a better fit in css-contain, since they are not valid anywhere else.
The prose should explain that specs using <condition> should specify:
- Which types of conditions are allowed?
- Which types of conditions can be specified bare, i.e. without a function name.
To make this more concrete, this is the state of the current specs with conditionals with this framing:
| Host | supports() |
media() |
size() |
style() |
|---|---|---|---|---|
@container |
- | - | - | ✅ Bare |
@supports |
✅ Bare | - | - | - |
@media |
- | ✅ Bare | - | - |
@import |
- | ✅ | ✅ Bare | - |
if() |
✅ | ✅ | - | ✅ |
@if / @when |
✅ | ✅ | - | ✅ |
While this change is editorial, I think it will pave the way for a lot of quick DX wins involving mixing and matching conditions (e.g. supports() in @media.
It could also allow creating JS APIs that handle conditions generically, avoiding the current issue of e.g. having matchMedia() for media queries, but no way to detect when a container query matches or not.
Activity
[-][css-values-4][Editorial] `<boolean>` type that other specs reference[/-][+][css-values-4][Editorial] `<condition>` type that other specs reference[/+][css-values-4] Add generic <boolean> grammar, so the increasing numbe…
tabatkins commentedon Jun 17, 2024
Committed a first pass at the generic
<boolean>grammarLeaVerou commentedon Jun 17, 2024
Thanks! I think the ergonomics will become more clear once we edit specs to reference it too.
Btw if we call it
<boolean>that sort of implies we also have constants liketrueandfalse. If we don’t want that, perhaps<condition>is more clear.cdoublev commentedon Aug 13, 2024
Can you please tell me if you plan to use context-sensitive production notations?
<@media/bool-test> = <media-feature><@supports/bool-test> = <supports-feature><rgb()/calc-keyword> = r | g | b | alpha | <calc-constant-keyword><width/intrinsic-size-keyword> = auto | min-content | max-contentMaybe the form should be
@media <bool-test> = <media-feature>because I am not sure how to annotate<context> <type> = valueusing the above form.A CSS parser would need to look for the closest production, ie.
<local><type>has priority over (global)<type>.I do not know if
<dfn for="@foo"><type></dfn> = valuewould be equivalent to<dfn><@rule/type></dfn> = value.I think the remaining changes are:
... and this would need to be defined either in prose or as suggested above:
<bool-test><container-condition>(<container-query>) | (<size-feature>) | style(<style-query>)supports()<supports-feature><media-query><media-feature>@supports<supports-feature>I am not sure for
if()and@when.[css-values-5] Define <boolean [test]> multiplier #10457
fantasai commentedon Oct 28, 2024
@tabatkins and I drafted up a
<<boolean [ test ]>>multiplier type into css-values-5. We think this covers the use cases pretty well, and should hopefully be reasonably easy to understand. See https://drafts.csswg.org/css-values-5/#boolean Agenda+ to review with the CSSWG.[css-values-5] Be consistent about brackets #10457
cdoublev commentedon Oct 31, 2024
Some minor things... (edit: fixed in 963fd9f)
I do not understand what the plural (emphasized below) refers to:
I think "evaluates" is more appropriate than "represents" (which is already used in the quote above):
I think
<boolean>should be<boolean[ <test> ]>on the second line:(edit) never mind, I guess the spec of container queries will be updated accordingly.<size-query>does not exist and should be<size-feature>:Perhaps syntax attribute names should be considered, noting that authors can now specify a value including a
<syntax>. For example,<number range=[0,∞] unit=px>and<boolean from=[<test>]or similar.[css-values-5] Address cdoublev's review #10457
css-meeting-bot commentedon Nov 7, 2024
The CSS Working Group just discussed
[css-values-4][Editorial] `<condition>` type that other specs reference, and agreed to the following:RESOLVED: Add <boolean-expr[...]> as a value definition syntax function multiplying its argument into a boolean expression microsyntaxThe full IRC log of that discussion
<TabAtkins> fantasai: we have a lot of places we'<TabAtkins> fantasai: we're using the not/and/or microsyntax - MQs, SQs, style queries, etc
<TabAtkins> fantasai: and now if()
<TabAtkins> fantasai: So we decided it would be more understandable to factor out that commonality into its own syntax "multiplier"
<TabAtkins> fantasai: similar to * and # in grammars
<TabAtkins> fantasai: So we introduced `<boolean [<grammar-here>]>`
<TabAtkins> fantasai: This isn't for authors to write, it's part of our Value Definition Syntax
<fantasai> https://drafts.csswg.org/css-values-5/#boolean
<TabAtkins> fantasai: whatever's inside the brackets is a parameter for the boolean tree (it's the leaves of the and/or/not tree)
<fantasai> https://drafts.csswg.org/css-values-5/#value-defs
<TabAtkins> fantasai: It's defined here, and also in the valdefs list
<TabAtkins> fantasai: [describes the syntax]
<TabAtkins> astearns: Currently it's just in Values 5, hasn't moved to toher specs?
<TabAtkins> fantasai: right
<dbaron> btw my comment about naming was about sounding like true/false rather than and/or/not
<fantasai> TabAtkins: we have an example of applying it to @container queries, since that's a complex grammar
<fantasai> TabAtkins: makes it easier to understand
<fantasai> astearns: [reads dbaron's comment]
<fantasai> TabAtkins: Lea also had this comment
<fantasai> TabAtkins: open to suggestions
<TabAtkins> fantasai: we didn't want to go with "condition" because it's such a generic term, seemed like it would actually be less clear
<TabAtkins> dholbert: "boolean-condition"?
<TabAtkins> fantasai: note that it is a functinoal syntax, not just `<boolean>` by itself, there's something between the [].
<TabAtkins> astearns: do we want any particular resoltion?
<TabAtkins> fantasai: if we're happy, we can accept adding it to the VDS
<TabAtkins> astearns: I think I'd like to noodle on the name a bit more
<TabAtkins> astearns: but i don't really have an idea of what to repalce it with
<TabAtkins> fantasai: we could make it longer with `<boolean-expression [...]>` but unsure if that's clearer
<TabAtkins> dholbert: makes it clearer it's not just true/false in the programming sense
<TabAtkins> dholbert: in the issue I saw a bunch of `<*-condition>` grammar terms used with it, so maybe `<boolean-condition>` would be good to follow it
<TabAtkins> fantasai: What we're trying to say is that this is the epxression syntax, not the conditions themselves. The condition is inside the []
<fantasai> <boolean[ <test> ]> = not <boolean-group> | <boolean-group>
<fantasai> [ [ and <boolean-group> ]*
<fantasai> | [ or <boolean-group> ]* ]
<fantasai> <boolean-group> = <test> | ( <boolean[ <test> ]> ) | <general-enclosed>
<TabAtkins> fantasai: [explains]
<TabAtkins> fantasai: it's kinda a syntactic function in the same way as + is, just more sophisticated
<fantasai> <container-query> = <boolean[ <cq-test> ]>
<TabAtkins> astearns: I think I do prefer boolean-expr in that last example
<TabAtkins> fantasai: ok
<kbabbitt> I like <boolean-expression[...]> as well
<TabAtkins> fantasai: so should we resolve to add boolean-expression?
<kbabbitt> boolean-expr is fine too
<TabAtkins> TabAtkins: i really want to shorten it to expr, I did that reflexively when minuting
<fantasai> PROPOSED: Add <boolean-expression[...]> as a value definition syntax function multiplying its argument into a boolean expression microsyntax
<TabAtkins> fantasai: i'm fine, tho we don't usually use shortened terms
<fantasai> fantasai: it would be exposed in @Property?
<TabAtkins> astearns: let's propose it with boolean-expr
<fantasai> TabAtkins: no, not unless we say so
<TabAtkins> astearns: objection?
<fantasai> RESOLVED: Add <boolean-expr[...]> as a value definition syntax function multiplying its argument into a boolean expression microsyntax
[css-values-5] Replace <boolean[]> with <boolean-expr[]> #10457
svgeesus commentedon Nov 13, 2024
So Needs Edits is removed (for values 5) but the specs listed at the top of the issue still all need to be edited.
Rename <boolean[]> into <boolean-expr[]> (fixes #307)
cdoublev commentedon Jul 28, 2025
I am not sure this is actually a requirement, but it is at least a problem for
w3c/reffy:<boolean-expr-group>is included in the production rule of<boolean-expr[<test>]>but it is not defined elsewhere.<<boolean-expr-group>>does not work in<xmp>, which is presumably used instead of<pre>to avoid the Bikeshed error from the unrecognized grammar<boolean-expr[<test>]> = ....Fwiw,
<boolean-expr> = ...would make sense to me. I see[<test>]the same way as a numeric range in<length-percentage [0,]>.Relatedly, I do not quite understand the naming of
<boolean-expr-group>from reading its production and the prose, which seems to be suggesting<boolean-condition>instead (emphasize added):<general-enclosed>is unknown stuff. How does<test>represent a boolean expression group?