@@ -76,39 +76,36 @@ Functional Notation Definitions</h3>
7676 See [[css-values-4#component-functions]] .
7777
7878<h4 id=component-function-commas>
79- Commas and Semicolons in Functions </h4>
79+ Commas in Function Arguments </h4>
8080
8181 [=Functional notation=] often uses commas
8282 to separate parts of its internal grammar.
8383 However, some functions
8484 (such as ''mix()'' )
8585 allow values that, themselves,
8686 can contain commas.
87+ These values
88+ (currently <<whole-value>> , <<declaration-value>> , and <<any-value>> )
89+ are <dfn export>comma-containing productions</dfn> .
8790
8891 To accommodate these sorts of grammars unambiguously,
89- commas in functional grammars are <em> implicitly upgradeable</em> to semicolons in Level 5;
90- that is,
91- commas in a [=functional notation=] 's grammar
92- can instead be represented as <<semicolon-token>> s.
93- This is all-or-nothing:
94- either every comma in the [=functional notation=] must be written as a semicolon,
95- or none of them must be.
96-
97- When a [=functional notation=] is parsed,
98- initially commas (<css> ,</css> ) and comma-multipliers (<css> #</css> )
99- in the grammar match only <<comma-token>> s in the value,
100- and any [=comma-containing productions=] are not allowed to contain <<comma-token>> s
101- (the productions must be interpreted as ending before the comma).
102- If a <<semicolon-token>> is encountered while parsing the [=functional notation=] ,
103- the contents must be <em> re-interpreted</em> ,
104- with commas and comma-multipliers in the grammar matching only <<semicolon-token>> s in the value,
105- and [=comma-containing productions=] being allowed to contain <<comma-token>> s.
106-
107- Commas contained in productions defined as <dfn>comma-containing productions</dfn>
108- (such as <<any-value>> or <<whole-value>> )
109- are not implicitly upgradeable.
110- Even when a [=functional notation=] is being re-interpreted with semicolons,
111- these productions end when a <<semicolon-token>> is encountered.
92+ the [=comma-containing productions=] can be optionally wrapped in curly braces {}.
93+ These braces are syntactic, not part of the actual value.
94+ Specifically:
95+
96+ * A [=comma-containing production=] can either start with a "{" token, or not.
97+ * If it does not start with a "{" token,
98+ then it cannot contain commas or {} blocks,
99+ in addition to whatever specific restrictions it defines for itself.
100+ (The production stops parsing at that point,
101+ so the comma or {} block is matched by the next grammar term instead;
102+ probably the function's own argument-separating comma.)
103+ * If it does start with a "{" token,
104+ then the production matches just the {} block that the "{" token opens.
105+ It represents the <em> contents</em> of that block,
106+ and applies whatever specific restrictions it defines for itself
107+ to those contents,
108+ ignoring the {} block wrapper.
112109
113110 <div class="example">
114111 For example, the grammar of the ''random-item()'' function is:
@@ -123,56 +120,80 @@ Commas and Semicolons in Functions</h4>
123120 like:
124121
125122 <pre>
126- list-style: random-item(--x, disc, circle, square);
127- </pre>
128-
129- It is <em> allowed</em> , however,
130- to "upgrade" the commas to semicolons,
131- like:
132-
133- <pre>
134- list-style: random-item(--x; disc; circle; square);
135- </pre>
136-
137- Both of the above mean the exact same thing.
138- However, mixing commas and semicolons does not work;
139- the following can produce an invalid value after substitution:
140-
141- <pre>
142- list-style: random-item(--x; disc, circle; square);
123+ font-family: random-item(--x, serif, sans-serif, monospace);
143124 </pre>
144125
145- because it represents choosing between two values
146- (<css> disc, circle</css> and <css> square</css> )
147- and <css> disc, circle</css> is not a valid 'list-style' value.
148-
149126 However, sometimes the values you want to choose between
150127 need to include commas.
151- For example, in 'font-family' :
128+ When this is the case,
129+ wrapping the values in {}
130+ allows their commas to be distinguished
131+ from the function's argument-separating commas:
152132
153133 <pre>
154- font-family: random-item(--x; Times, serif; Arial, sans-serif; Courier, monospace);
134+ font-family: random-item(--x, { Times, serif}, { Arial, sans-serif}, { Courier, monospace} );
155135 </pre>
156136
157137 This randomly chooses one of three font-family lists:
158138 either ''Times, serif'' , or ''Arial, sans-serif'' , or ''Courier, monospace'' .
159- But if only single fonts were needed for each choice,
160- commas <em> could</em> have been used to separate them:
139+
140+ This is not all-or-nothing;
141+ you can use {} around <em> some</em> arguments that need it,
142+ while leaving others bare when they don't need it.
143+ You are also allowed to use {} around a value when it's not strictly required.
144+ For example:
161145
162146 <pre>
163- font-family: random-item(--x, serif, sans-serif, monospace);
147+ font-family: random-item(--x, {Times, serif} , sans-serif, { monospace} );
164148 </pre>
165149
150+ This represents choosing between three font-family lists:
151+ either ''Times, serif'' , or ''sans-serif'' , or ''monospace'' .
152+
153+ However, this {}-wrapping is <em> only</em> allowed for some function arguments--
154+ those defined as [=comma-containing productions=] .
155+ It's not valid for any other productions;
156+ if you use {} around other function arguments,
157+ it'll just fail to match the function's grammar
158+ and become invalid.
159+ For example, the following is <strong> invalid</strong> :
160+
161+ <pre>
162+ background-image: linear-gradient(to left, {red}, magenta);
163+ </pre>
166164 </div>
167165
168- [=Functional notations=] are serialized with commas (rather than semicolons) whenever possible.
166+ Note: Because {} wrappers are allowed even when not explicitly required,
167+ they can be used defensively around values
168+ when the author isn't sure if they'll end up containing commas or not,
169+ due to [=arbitrary-substitution functions=] like ''var()'' .
170+ For example, ''font-family: random-item(--x, {var(--list1)}, monospace)''
171+ will work correctly
172+ regardless of whether the ''--list1'' custom property
173+ contains a comma-separated list or not.
174+
175+ [=Functional notations=] are serialized without {} wrappers whenever possible.
169176
170177 The following generic productions are [=comma-containing productions=] :
171178
172179 * <<any-value>>
173180 * <<whole-value>>
174181 * <<declaration-value>>
175182
183+ For legacy compat reasons,
184+ the <<declaration-value>> defined the fallback value for ''var()''
185+ is a <dfn export>non-strict comma-containing production</dfn> .
186+ It ignores the rules restricting what it can contain
187+ when it does not start with a "{" token:
188+ it is allowed to contain commas and {} blocks.
189+ It still follows the standard [=comma-containing production=] rules
190+ when it <em> does</em> start with a "{" token, however:
191+ the fallback is just the contents of the {} block,
192+ and doesn't include the {} wrapper itself.
193+
194+ Other contexts <em> may</em> define that they use [=non-strict comma-containing productions=] ,
195+ but it <em> should</em> be avoided unless necessary.
196+
176197<h2 id="level-4-extensions">
177198Extensions to Level 4 Value Types</h3>
178199
0 commit comments