Skip to content

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

Closed
@chris-morgan

Description

@chris-morgan

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:

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

<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

<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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions