Skip to content

Less language Nesting

SomMeri edited this page Mar 4, 2013 · 15 revisions

A ruleset can be nested into another ruleset. Nested rulesets make no difference to the outer ruleset, it will be compiled the same way as usually.

Selectors of the nested ruleset are combined with outer selectors. This helps to avoid repetition whenever style sheet contains multiple rulesets with similar selectors. Common part is placed into the outer ruleset while each nested ruleset can add its own parts.

Nested ruleset can use all variables and mixins defined in the outer one, but it will not contain outer selector css properties.

Default Combination

Unless specified otherwise, all nested selectors are considered to be descendants of all outer selectors:

h1, h2 {
  padding: 2 2 2 2;
  :nested, p {
    margin: 3 3 3 3;
  }
}

Output:

h1, h2 {
  padding: 2 2 2 2;
}
h1 :nested, h2 :nested, h1 p, h2 p {
  margin: 3 3 3 3;
}

Nested ruleset can use all variables and mixins defined inside the outer one:

@scope: 1;
h1, h2 {
  scope: @scope;
  :nested, p {
    scope: @scope;
  }
  @scope: 2;
}

Output:

h1, h2 {
  padding: 2;
}
h1 :nested, h2 :nested, h1 p, h2 p {
  margin: 2;
}

Joining Combiner

Prefix nested selector by and css combiner to override default "descendant" behavior:

h1, h2 {
  padding: 2 2 2 2;
  + :nested, >p {
    margin: 3 3 3 3;
  }
}

Output:

h1, h2 {
  padding: 2 2 2 2;
}
h1 + :nested, h2 + :nested, h1 > p, h2 > p {
  margin: 3 3 3 3;
}

Appender

Use appender & to override the default "outer selector comes first" behavior. Appender can be placed anywhere inside the nested selector and each nested selector can contain multiple appenders. The compilation replaces it with all outer selectors. Both combinators and whitespaces before and after the appender are respected.

Appender in the Middle

Appender is replaced by all outer selectors:

:first, :second {
  padding: 2 2 2 2;
  h1&:hover, h2 & :visit {
    margin: 3 3 3 3;
  }
}

Output:

:first,
:second {
  padding: 2 2 2 2;
}
h1:first:hover,
h1:second:hover,
h2 :first :visit,
h2 :second :visit {
  margin: 3 3 3 3;
}

Multiple Appenders

Multiple appenders generate all combinations of outer selectors:

:first, :second {
  padding: 2 2 2 2;
  h1&:hover& {
    margin: 3 3 3 3;
  }
}

Output:

:first,
:second {
  padding: 2 2 2 2;
}
h1:first:hover:first,
h1:first:hover:second,
h1:second:hover:first,
h1:second:hover:second {
  margin: 3 3 3 3;
}

Deep Nesting

Nested rules can go arbitrary deep:

h1 {
  padding: 2 2 2 2;
  p {
    margin: 3 3 3 3;
    &:hover {
      width: 2;
    }
  }
}

Output:

h1 {
  padding: 2 2 2 2;
}
h1 p {
  margin: 3 3 3 3;
}
h1 p:hover {
  width: 2;
}

Combinators and Whitespaces

Both combinators and whitespaces before and after the appender are respected:

h1, h2 {
  padding: 2 2 2 2;
  &:direct, & + :child, & :descendant {
    margin: 3 3 3 3;
  }
}
:first, :second {
  padding: 2 2 2 2;
  descendant &, child + &, direct& {
    margin: 3 3 3 3;
  }
}

Output:

h1, h2 {
  padding: 2 2 2 2;
}
h1:direct, h2:direct,
h1 + :child, h2 + :child,
h1 :descendant, h2 :descendant {
  margin: 3 3 3 3;
}
:first, :second {
  padding: 2 2 2 2;
}
descendant :first, descendant :second,
child + :first, child + :second,
direct:first, direct:second {
  margin: 3 3 3 3;
}

Combinator Conflict

In case of conflict, the inner selector combinator wins:

> h1 {
  name + & {
    declaration: 1 2;
  }
}

Output:

name + h1 {
  declaration: 1 2;
}