Skip to content

Less language Directives Bubbling

Mária Jurčovičová edited this page Apr 3, 2015 · 21 revisions

Css stylesheet directives like @font-face, @media or @supports must normally be placed on style sheet top level or inside other directives. Less allows them also to be nested into rulesets, mixins or any other less structure.

Css contains two kinds of directives:

Both conditional and non-conditional directives "bubble up" on top of stylesheet during compilation, however they do it in two different ways.

Non-Conditional Directives

Non-conditional directives such as font-face or keyframes are removed from rulesets they are in and placed on top. The relative order against other elements inside the same ruleset remains unchanged.

Example input:

#a {
  color: blue;
  @font-face {
    src: made-up-url;
  }
  padding: 2 2 2 2;
}

compiles into:

#a {
  color: blue;
}
@font-face {
  src: made-up-url;
}
#a {
  padding: 2 2 2 2;
}

Conditional Directives

Conditional directives e.g., @media, @supports and @document, define a condition under which css rules inside them apply. They are useful when you need changes in layout or colors for printing, small screen or device type.

They have to be placed on top of stylesheet too, so if the stylesheet contains complicated selectors structures, they have to be maintained on multiple places: outside of directives and inside each one.

Example of selector that must be maintained on two places:

.complicated .selector { //place 1
  margin: 4 4 4 4;
}
@media print {
  .complicated .selector {//place 2
    margin: 0 0 0 0;
  }
}

Conditional directives in Less can be nested and compiler converts them into equivalent css. As directive "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 it are applied to the same html elements as normally, but only if the conditions specified by directives are satisfied.

Following less compiles into above css:

.complicated .selector {
  margin: 4 4 4 4;
  @media print {
    margin: 0 0 0 0;
  }
}

Ruleset Nested in Directive

Nested directive can contain rulesets. The directive will bubble on top and selectors will be joined as usually. Following less:

#a {
  @media screen { 
    nested {
      color: green;
    }
  }
  color: blue;
}

compiles into:

#a {
  color: blue;
}
@media screen {
  #a nested {
    color: green;
  }
}

Directive Inside Directive

Directives bubbling keeps their relative order. Following less:

#a {
  @media screen { 
    nested {
      @supports (transform-origin: 5% 5%) {
        color: green;
        transform-origin: 5% 5%;
      }
    }
  }
  color: blue;
}

compiles into:

#a {
  color: blue;
}
@media screen {
  @supports (transform-origin: 5% 5%) {
    #a nested {
      color: green;
      transform-origin: 5% 5%;
    }
  }
}