This proposal defines how Sass handles media queries with features written in a range context.
This section is non-normative.
Media features written in a range context will be parsed by Sass, with full
SassScript expressions allowed for the values except in cases where Sass's
operators would be ambiguous with range operators. Range-context media features
will be merged as all media features have been up to this point, by adding each
feature to the media query's "and"
-separated list.
While it would be possible to merge features more intelligently—for example,
(width > 200px) and (width < 600px)
could be merged into
(200px > width > 600px)
—doing so in general would add a great deal of
complexity to media merging, for very limited benefits in terms of output size
and readability.
The values of media features with the "range" type are heterogeneous, including
a <ratio>
type value type that Sass has no existing knowledge of. If Sass
were to support intelligent merging of these features, it would need to keep
abreast of any new value types supported by "range"-type media features. This
would violate Sass's general design principle of knowing as little about CSS as
possible.
Sass parses media queries twice. The first time is part of parsing the Sass stylesheet, at which point the queries may contain SassScript expressions and interpolation. The second parses the result of evaluating the SassScript as plain CSS.
This proposal defines a new syntax for media queries in Sass stylesheets. It is intended to replace the existing syntax.
Other than support for the range context syntax, this syntax is designed to represent the current behavior of all Sass implementations.
MediaQueryList ::= MediaQuery (',' MediaQuery)* MediaQuery ::= MediaType | (MediaType 'and')? MediaFeature ('and' MediaFeature)* MediaType ::= InterpolatedIdentifier InterpolatedIdentifier¹? MediaFeature ::= Interpolation | '(' Expression² ')' | '(' Expression² ':' Expression ')' | '(' Expression² Expression² ')' | '(' Expression² Expression² Expression² ')' | '(' Expression² Expression² Expression² ')'
1: This InterpolatedIdentifier
may not be the identifier "and"
.
2: These Expression
s may not contain binary operator expressions with the
operators =
, >
, >=
, <
, or <=
, except within parentheses (including
function calls and map literals) and square brackets.
The <mf-comparison>
, <mf-lt>
, and <mf-gt>
productions are defined in
Media Queries Level 4.
Note that Sass currently doesn't support parsing full media conditions according to the level 4 specification, since no browsers support it yet. See sass/sass#2538 for details.
Plain CSS media queries are parsed using the following syntax:
CssMediaQueryList ::= CssMediaQuery (',' CssMediaQuery)* CssMediaQuery ::= CssMediaType | (CssMediaType 'and')? CssMediaFeature ('and' CssMediaFeature)* CssMediaType ::= ¹? CssMediaFeature ::= '(' ')'
1: This Identifier
may not be the identifier "and"
.
The <ident-token>
production matches the railroad diagram
listed in CSS Syntax Level 3. The <declaration-value>
production uses
the definition from CSS Syntax Level 3,
consuming tokens only as needed until the production terminates.
This is the existing syntax Sass uses to reparse plain CSS media queries. Since they're already parsed using
<declaration-value>
, no change in behavior is necessary to support range-form queries.