5.2 KiB
Media Logic: Draft 1.1
This proposal adds support for the full Media Queries Level 4 syntax for media
conditions, including arbitrary boolean logic using and
, or
, and not
.
Table of Contents
Background
This section is non-normative.
For historical reasons, Sass fully parses media queries and allows SassScript to
be embedded directly in them, as in @media ($query: $value)
, in contrast to
most other at-rules in which SassScript can only be injected using
interpolation. This means that as CSS adds new media query syntax, Sass is
obligated to update its specification to accommodate it.
Media Queries Level 4 adds support for arbitrary boolean logic in media
queries, such as @media ((width >= 100px) and (width <= 800px)) or (grid)
.
Sass must therefore update its syntax accordingly.
Summary
This section is non-normative.
The proposal is relatively straightforward: it adds the new syntax to Sass's grammar. It is worth noting, though, that this will require a few breaking changes. These are unlikely to affect many real-world stylesheets, but they're worth highlighting nevertheless.
The new syntax allows any <media-condition>
to appear inside a
<media-in-parens>
. This means that queries beginning with (not
or ((
must be parsed as nested media queries, rather than SassScript expressions as
they have historically been parsed. We'll issue a short deprecation period for
the SassScript expressions in question, recommending users migrate them to
interpolation instead, then drop support and begin parsing them as media queries
for CSS compatibility.
Syntax
MediaQuery
Replace the definition of the MediaQuery
production with the following (with
all identifiers matched case-insensitively):
MediaQuery ::= MediaNot | MediaInParens (MediaAnd* | MediaOr*) | MediaType ('and' MediaNot | MediaAnd*) MediaType ::= InterpolatedIdentifier InterpolatedIdentifier¹? MediaNot² ::= 'not' MediaOrInterp MediaAnd² ::= 'and' MediaOrInterp MediaOr² ::= 'or' MediaOrInterp MediaOrInterp ::= Interpolation | MediaInParens MediaInParens ::= '(' Expression³ ')' | '(' Expression³ <mf-comparison> Expression³ ')' | '(' Expression³ <mf-lt> Expression³ <mf-lt> Expression³ ')' | '(' Expression³ <mf-gt> Expression³ <mf-gt> Expression³ ')' | '(' MediaNot ')' | '(' MediaInParens (MediaAnd* | MediaOr*) ')'
-
This
InterpolatedIdentifier
may not be the identifier"and"
. -
No whitespace is allowed between the identifier and the
MediaOrInterp
in these productions. -
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. -
Begin with the case-insensitive identifier
"not"
. -
Begin with the character
"("
.
-
CssMediaQuery
Replace the definition of the CssMediaQuery
production with the following (with
all identifiers matched case-insensitively):
CssMediaQuery ::= CssMediaCondition | CssMediaType ('and' CssMediaNot | CssMediaAnd*) CssMediaType ::= <ident-token> <ident-token>¹? CssMediaCondition ::= CssMediaNot | CssMediaInParens (CssMediaAnd* | CssMediaOr*) CssMediaNot ::= 'not' CssMediaInParens CssMediaAnd ::= 'and' CssMediaInParens CssMediaOr ::= 'or' CssMediaInParens CssMediaInParens ::= '(' <declaration-value> ')'
- This
<ident-token>
may not be the identifier"and"
.
Deprecation Process
Before this specification is applied in full force, it will be applied with the following modifications:
-
MediaInParens
will not allow the productions'(' MediaNot ')'
or'(' MediaInParens (MediaAnd* | MediaOr*) ')'
. -
If the first
Expression
in aMediaInParens
production begins with the case-insensitive identifier"not"
or the character"("
, emit a deprecation warning.