Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[css-values] Grammar syntax for defining default values for optional productions #11189

Open
weinig opened this issue Nov 12, 2024 · 1 comment

Comments

@weinig
Copy link

weinig commented Nov 12, 2024

As part of an ongoing effort to generate the parsing and serialization of CSS values from the grammars in specs, one of the most prominent missing pieces of information is the prose defined "default values" for optional productions.

To give some concrete examples, lets take a look at the grammar for the blur() function:

blur() = blur( <length>? )

In prose below the grammar is the text "Default value when omitted is 0px."

If instead, that information was available in a machine readable way, parsing and serialization of would be directly implementable.

This would similarly be beneficial for testing.

I don't have strong opinions on the specifics of a syntax extension, so as a strawman I propose ?=[default value here].

For the example above, this might look like:

blur() = blur( <length>?=[0px] )

This won't work for everything, some defaults are quite complicated, but I think it would move things forward.

@weinig
Copy link
Author

weinig commented Nov 16, 2024

To make this more concrete, and show some weaknesses, here are some additional examples of where this could be used:

CSS Images 4

https://drafts.csswg.org/css-images-4/#typedef-linear-gradient-syntax

linear-gradient() = linear-gradient(
  [ [ <angle> | to <side-or-corner> ]?=[to bottom] || <color-interpolation-method>?=[oklab] ] ,
  <color-stop-list>
)
<side-or-corner> = [left | right] || [top | bottom]

https://drafts.csswg.org/css-images-4/#radial-gradients
Radial gradient is a bit hard to fit in the scheme due to divergent defaults based on whether an ellipse or circle should be used, though I expect there is an expanded form of the grammar that could work).

https://drafts.csswg.org/css-images-4/#typedef-conic-gradient-syntax

conic-gradient() = conic-gradient( [ <conic-gradient-syntax> ] )
<conic-gradient-syntax> =
  [ [ [ from <angle> ]?=[from 0deg] [ at <position> ]?=[at center ] || <color-interpolation-method> ]?=[oklab] ,
  <angular-color-stop-list>)

https://drafts.csswg.org/css-images-4/#stripes

<image-1D> = <stripes()>
<stripes()> = stripes( <color-stripe># )
<color-stripe> = <color> && [ <length-percentage> | <flex> ]?=[1fr]

CSS Shapes

https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-inset
It might be useful to be able to specify the behavior behavior of {1,4} adhearing to the "margin" rules. Doing so, would require a way for default values to refer to specific elements within production The spec has this prose: "the omitted values default in the same way as the margin shorthand: an omitted second or third value defaults to the first, and an omitted fourth value defaults to the second".

<inset()> = inset(
  <length-percentage>{1,4}
  [ round <'border-radius'> ]?=[round 0px]
)

and example using made up but hopefully understandable synax for how the "margin" rules could be specified would be something like:

<length-percentage>{1,4} =
    [ <length-percentage>[name=a] ]=[a a a a]
  | [ <length-percentage>[name=a] <length-percentage>[name=b] ]=[a b a b]
  | [ <length-percentage>[name=a] <length-percentage>[name=b] <length-percentage>[name=c] ]=[a b c b]
  | [ <length-percentage> <length-percentage> <length-percentage> <length-percentage> ]

https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-xywh

<xywh()> = xywh(
  <length-percentage>{2} <length-percentage [0,∞]>{2}
  [ round <'border-radius'> ]?=[round 0px]
)

https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-rect

<rect()> = rect(
  [ <length-percentage> | auto ]{4}
  [ round <'border-radius'> ]?=[round 0px]
)

https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-circle
The spec actually doesn't specify what should happen in <radial-size> is omited, but CSS Images defaults to farthest-corner.

<circle()> = circle(
  <radial-size>?=[farthest-corner]
  [ at <position> ]?=[at center]
)

https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-ellipse
The spec actually doesn't specify what should happen in <radial-size> is omited, but CSS Images defaults to farthest-corner.

<ellipse()> = ellipse(
  <radial-size>?=[farthest-corner]
  [ at <position> ]=[at center]
)

https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-polygon

<polygon()> = polygon(
  <'fill-rule'>?=[nonzero]
  [ round <length> ]?=[round 0px] ,
  [<length-percentage> <length-percentage>]#
)

https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-path
No default can be used for <'fill-rule'> for path, as the spec says it is context dependent: "Defaults to nonzero if omitted, unless the function is being used in a context such as SVG shapes where the fill-rule property is relevant. In that case an omitted value will use the computed value of the fill-rule property"

<path()> = path(
  <'fill-rule'>? ,
  <string>
)

CSS Filters

Filters give some interesting cases. A lot is covered, but missing is syntax to specify:

  • how normalize to
  • haw a value range should be clamped rather than fail to parse (e.g. grayscale might be grayscale( [ <number [0,∞] clamp[0,1]> | <percentage [0,∞] clamp[0,100%]> ]?=[1] ))

https://drafts.fxtf.org/filter-effects/#funcdef-filter-blur

blur() = blur( <length [0,∞]>?=[0px] )

https://drafts.fxtf.org/filter-effects/#funcdef-filter-brightness

brightness() = brightness( [ <number [0,∞]> | <percentage [0,∞]> ]?=[1] )

https://drafts.fxtf.org/filter-effects/#funcdef-filter-contrast

contrast() = contrast( [ <number [0,∞]> | <percentage [0,∞]> ]?=[1] )

https://drafts.fxtf.org/filter-effects/#funcdef-filter-drop-shadow

drop-shadow() = drop-shadow( [ <color>?=[currentcolor] && [<length> <length> <length>?=[0px]  ] )

https://drafts.fxtf.org/filter-effects/#funcdef-filter-grayscale

grayscale() = grayscale( [ <number [0,∞]> | <percentage [0,∞]> ]?=[1] )

https://drafts.fxtf.org/filter-effects/#funcdef-filter-hue-rotate

hue-rotate() = hue-rotate( [ <angle> | <zero> ]?=[0deg] )

https://drafts.fxtf.org/filter-effects/#funcdef-filter-invert

invert() = invert( [ <number [0,∞]> | <percentage [0,∞]> ]?=[1] )

https://drafts.fxtf.org/filter-effects/#funcdef-filter-opacity

opacity() = opacity( [ <number [0,∞]> | <percentage [0,∞]> ]?=[1] )

https://drafts.fxtf.org/filter-effects/#funcdef-filter-saturate

saturate() = saturate( [ <number [0,∞]> | <percentage [0,∞]> ]?=[1] )

https://drafts.fxtf.org/filter-effects/#funcdef-filter-sepia

sepia() = sepia( [ <number [0,∞]> | <percentage [0,∞]> ]?=[1] )

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

2 participants