-
Notifications
You must be signed in to change notification settings - Fork 47
Less language Media Bubbling and Merging
Conditional directives e.g. css @at-rules are used to define rules valid only on certain media types (@media), only if the browser implements certain features (@supports) or only if the page is located on specified url (@document).
For example, Css @media rule can be to define rulesets valid only when printing document or on small screen and ignored otherwise. According to css specification, @media rule must be placed on style sheet top level. So, if you use complicated selectors structures, you have to maintain them on multiple places: outside of media and inside each different media type.
Less @media rule can be nested into rulesets, mixins or any other less structures. Compiler interprets nested media as "make exception for this kind of media". The advantage is simple: you do not have to maintain the same rulesets and selectors structures inside multiple media types.
Nested media rules bubble on to of style sheet and:
- copy all encountered selectors into their own bodies,
- merge their own media queries with all media queries encountered on the way up.
As media rule "bubble" on top of style sheet, it collects all encountered selectors and copies them into its own body. As a result, all declarations written inside nested media are going to be applied to the same html elements as normally, but only if their media queries are satisfied.
Example input:
#a {
color: blue;
padding: 2 2 2 2;
// printed document should be rendered differently - it should not be colored
@media print {
color: black;
}
}
compiles into:
#a {
color: blue;
padding: 2 2 2 2;
}
@media print { // all is good except the color
#a {
color: black;
}
}
It is also possible to nest rulesets inside nested media:
#a {
@media screen {
nested {
color: green;
}
}
color: blue;
}
nested rulesets are combined as usually:
#a {
color: blue;
}
@media screen {
#a nested {
color: green;
}
}
Media merging happens when the compiler encounters media nested into another media. Whatever is written inside nested media is applied only if both inner and outer media queries are satisfied. It is very similar to rulesets nesting: outer media is compiled as usually, nested media make no difference to it. Inner media queries are combined with outer media queries.
Sample input:
@media print {
.class {
margin: 3 3 3 3;
color: black;
@media (max-width: 117px) { // margin should be smaller in small media
margin: 1 1 1 1;
}
}
}
compiles into:
@media print {
.class {
margin: 3 3 3 3;
color: black;
}
}
@media print and (max-width: 117px) { // print on small media should use smaller margin
.class {
margin: 1 1 1 1;
}
}
Any media can describe multiple mediums. If this is the case, then each medium query described by inner media type is combined with each medium query described by outer media:
@media print, screen {
.class {
// ... whatever ...
@media (max-width: 117px), (max-device-aspect-ratio: 1367/768) {
margin: 1 1 1 1;
}
}
}
compiles into:
@media print, handheld {
.class {
// ... whatever ...
}
}
@media print and (max-width: 117px), handheld and (max-width: 117px),
print and (max-device-aspect-ratio: 1367/768), handheld and (max-device-aspect-ratio: 1367/768) {
.class {
margin: 1 1 1 1;
}
}
CSS specification allows only one media type inside each media query. That media type can be followed by any number of media expressions joined by "and". If inner media type starts with a media type, resulting less style sheet is invalid. Such input is treated differently by less4j and less.js.
Less.js combines inner and outer media queries as they are and thus produce invalid CSS. Less4j ignores media type in inner media query and produces a warning.
Sample input:
@media print {
.class {
@media screen and (max-width: 117px){
margin: 1 1 1 1;
}
}
}
Less.js generated style sheet:
@media print and screen and (max-width: 117px) {
.class {
margin: 1 1 1 1;
}
}
Less4j generated style sheet:
@media print and (max-width: 117px) {
.class {
margin: 1 1 1 1;
}
}