[csswg-drafts] [css-env-1] Meaning of “syntactically valid” in env() has led to differing nonsense behaviour in browsers: it needs clarifying (#3792)

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

== [css-env-1] Meaning of “syntactically valid” in env() has led to differing nonsense behaviour in browsers: it needs clarifying ==
Refer to https://bugzilla.mozilla.org/show_bug.cgi?id=1539708#c2 for background. An issue will need to be filed on Chromium, the precise shape of which will depend on the outcome of this issue. Maybe WebKit too; not sure.

The problem relates to https://drafts.csswg.org/css-env-1/#env-function:

> If a property contains one or more env() functions, and those functions are syntactically valid, the entire property’s grammar must be assumed to be valid at parse time. It is only syntax-checked at computed-time, after env() functions have been substituted.

I’m not confident in my understanding of the terms involved, but I *think* that is just saying that you can’t classify a value as invalid out-of-hand at parse time, but will need to wait until you compute it, to decide whether it’s valid. (If that’s not what it does actually mean, I will glibly assert that it’s still what it *should* mean, and what a non-spec-reading human will expect it to do.)

However, Firefox seems to have only implemented the first part and not compute-time syntax-checking, and Chrome also seems to have missed the compute-time syntax-checking, and moreover sensibly ignored a small part of the stipulated parse time validity checking. Not sure about Safari, as I don’t have access to a Mac.

I’ve created this issue to confirm the correct interpretation, and request that a clarifying note be added to this place in the spec, since this is evidently a fiddly detail for implementers.

I think this is a fairly important issue for css-env, due to interactions with other upcoming specs. The code that precipitated my coworker finding this seems quite reasonable, and was roughly this:

```css
margin-bottom: 15px;
margin-bottom: env(safe-area-inset-bottom, 15px);
margin-bottom: max(env(safe-area-inset-bottom, 15px), 15px);
```

That one could need to wrap the third line up in `@supports (margin-bottom: env(safe-area-inset-bottom)) and (margin-bottom: max(0, 15px))` would be decidedly unfortunate.

----

**Test case 1:** `env()` that is substituted with an invalid value

```html
<body style="background-color:limegreen;background-color:env(bar, 1)">
```

A human reading this will expect it to be `limegreen`, since `background-color: env(bar, 1)` will become, by substitution, `background-color: 1`, which is invalid.

Firefox accepts the second rule as valid, but equates it to… I’m not actually sure what it is technically, but `initial` or `unset`, at a guess? So the limegreen background is overridden, and you get a white background.

Chrome does the same.

Safari I have no access to, so I’m not sure what it may do. *(Feel free to update this text with the result of testing it in Safari; or I will if someone comments it.)*

----

**Test case 2:** `env()` used inside an unknown function

```html
<body style="margin:10em;margin:foo(env(bar, blue))">
```

A human reading this will expect `margin: foo(env(bar, blue))` to be ignored, since there is no function `foo()`; and so for the body margin to be 10em.

Firefox treats it as valid but the default value of zero, again.

Chrome decides that since it doesn’t have a `foo()` function, the value is invalid, and uses 10em. I’d guess it does this at parse time.

Safari I have no access to, so I’m not sure what it may do.

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

Received on Tuesday, 2 April 2019 12:45:52 UTC