Skip to content

[css-env] Consider value-level parsing like calc() rather than token-level like var() #3285

Open
@SimonSapin

Description

@SimonSapin

Background

The syntax of the calc() function is defined "at the value level":

https://drafts.csswg.org/css-values/#calc-notation

A math function can be used wherever <length>, <frequency>, <angle>, <time>, <flex>, <resolution>, <percentage>, <number>, or <integer> values are allowed.

This allows both authors and implementers to only consider those functions in contexts where these value can be used. For example, display: calc(…) is never valid for any .

The var() function however works "at the token stream level", before even considering the value syntax of a given property:

https://drafts.csswg.org/css-variables/#using-variables

The var() function can be used in place of any part of a value in any property on an element.

Being so general is useful for var() because many authors will be defining custom properties with arbitrary bits of syntax. We don’t want the spec to have to anticipate and enumerate each value type that could be used in custom property values.

However, this causes var() to "infect" more of the language. The presence of a var() function somewhere in the middle of a declaration affects the behavior of the entire declaration in ways that both authors and implementers need to be aware of and deal with:

https://drafts.csswg.org/css-variables/#using-variables

If a property contains one or more var() 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-value time, after var() functions have been substituted.

In this sense, var() is a more fundamental part of CSS syntax than just another feature that can be used in values.

env()

Currently, the syntax of the env() function is defined in a way very similar to var():

https://drafts.csswg.org/css-env-1/#env-function

The env() function can be used in place of any part of a value in any property on any element, or any part of a value in any descriptor on any at-rule, and in several other places where CSS values are allowed.

I think it doesn’t need to be, and it should be redefined in a way similar to the calc() function: it is an additional set of valid values for a given set of types like <length>.

The spec defines a closed set of environment variables, and all of them are currently defined as <length>. In the future if/when new variables of other types are added (possibly <color>?), we can extend parsing support to those types.

Compat

I understand that this feature is already shipping in some browsers (despite not having a working draft yet). Hopefully it was only shipped recently enough that relatively few sites use it, and it is simple enough that they mostly use it ways (only using length variables in length contexts) that are similar to each other and not affected by this proposed change.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions