less.js
less.js copied to clipboard
Nested @media blocks are combined in a non-compliant way.
According to the CSS spec, media type (screen, print etc) must be first on the list and all the other conditions (for example (max-width: 800px)) must follow after the media type.
To reproduce:
@media (max-width: 800px) {
@media screen {
.selector {color: black}
}
}
Current behavior:
Less compiler combines nested media conditions in a way that is not compliant with the spec, putting media type between conditions or after them.
@media (max-width: 800px) and screen {
.selector {
color: black;
}
}
Expected behavior:
Media type should be put into the first position in the media query, like so:
@media screen and (max-width: 800px) {
.selector {
color: black;
}
}
Environment information:
lessversion: 4.1.3, including the official playgroundnodejsversion: anyoperating system: any
Additional notes
Even though it might seem trivial to re-order the example above to produce correct results, it's not always possible since the inner @media screen might come from a third party (I'm working with antd) that I can't modify.
It seems like most browsers don't mind media conditions being out of spec (or I didn't observe the effects), however this issue prevents me from using https://parceljs.org/ which implements pretty strict standards checking and chokes at the less output, producing Unexpected token Ident("screen"). The fixed snippet where media-type comes first is processed correctly by parcel.
@tsx Can you link more precisely to where it specifies order?
The spec section I linked https://drafts.csswg.org/mediaqueries-5/#typedef-media-query-list says:
<media-query> = <media-condition> | [ not | only ]? <media-type> [ and <media-condition-without-or> ]?
Which means it's either media-condition alone or media-type (like screen) followed by and ... some extra conditions. Note that media-type like screen is not a condition, so the only acceptable place for it is before the conditions.
Also see the railroad diagram in https://drafts.csswg.org/mediaqueries-5/#media if that helps to visualise things.
I will just say quickly that Less doesn't parse media queries into "sections of meaning" so much as it just parses parenthetical groups, which it joins with and. Similar to the fact that it doesn't parse property values into values that could be combined, say, into a shorthand value. All of them are sequences of generic CSS tokens, with special meaning attributed only to specific tokens insofar as they might be used in functions.
So, I would say you would probably just need to re-order your media queries, because it's unlikely this would change.