Skip to content

Less Language Detached Rulesets

Mária Jurčovičová edited this page Jul 1, 2014 · 41 revisions

Detached ruleset is a group of css properties, nested rulestes, media declarations or anything else stored in a variable. You can include it into a ruleset or another structure and all its properties are going to be copied there. You can also use it as a mixin argument and pass it around as any other variable.

Simple example:

// declare detached ruleset
@detached-ruleset: { background: red; };

// use detached ruleset
.top {
    @detached-ruleset(); 
}

compiles into:

.top {
  background: red;
}

Parentheses after detached ruleset call are mandatory. The @detached-ruleset; call would NOT work.

Content

Detached ruleset can contain everything an ordinary ruleset can: properties, nested rulesets, media declarations, variables declarations, mixins, etc. Variables and mixins defined inside mixins act as return values and are usable in caller. Detached ruleset call unlocks (returns) all its mixins into caller the same way as mixin calls do. However, returned variables never rewrite callers variables. Variables already present in callers local scope are not going to be rewritten.

It returns also all its variables, however variables returned from detached ruleset behave slightly differently then those returned from mixins.

Media inside detached ruleset:

// detached ruleset with nested media
@detached-ruleset: { 
    @media print {
    	.nested-ruleset {
            color: blue;
    	}
    }
};
// call detached ruleset
.caller {
    @detached-ruleset(); // use detached ruleset
}

compiles into:

@media print {
  .caller .nested-ruleset {
    color: blue;
  }
}

Detached ruleset copies all its mixins into caller:

// detached ruleset with nested media
@detached-ruleset: { 
    .mixin() {
        color:blue;
    }
};
// call detached ruleset
.caller {
    @detached-ruleset(); 
    .mixin();
}

compiled css:

.caller {
  color: blue;
}

It does NOT return variables, following results in an error:

detached-ruleset: { 
    @color:blue; //this variable is private
};
.caller {
    color: @color; //syntax error
}

Passed As Argument

Detached ruleset can be used as mixin argument. Next mixin wraps its argument into media declarations:

//mixin assumes that @rules parameter contains detached ruleset
.big-screen-exception(@rules) {
    @media screen and (min-width: 1200) {
    	//use detached ruleset from parameter
        @rules();
    }
}
.caller {
    color: red;
    //detached ruleset is sent as parameter
    .big-screen-exception({ color:blue a; });
}

compiles into:

.caller {
  color: red;
}
@media screen and (min-width: 1200) {
  .caller {
    color: blue a;
  }
}

Note: detached ruleset can not be used as parameter default. This limitation is present only in less.js, less4j supports it. Following is NOT allowed in less.js:

.mixin(@parameter: {default: default;}) { // syntax error: detached ruleset as default value
  @parameter();
}

Scoping

Scoping of detached rulesets is almost the same as mixins scoping. Detached ruleset can use all variables and mixins accessible on place where it is defined and where it is called. Otherwise said, both definition and caller scopes are available to it. If both scopes contains the same variable or mixin, declaration scope value takes precedence.

Detached mixin sees callers variables and mixins:

@detached-ruleset: {
  caller-variable: @callerVariable;
  .callerMixin();
};

selector {
  @detached-ruleset();

  //define variable and mixin
  @callerVariable: value;
  .callerMixin() {
    variable: declaration;
  }
}

compiles into:

selector {
  caller-variable: value;
  variable: declaration;
}

Variable and mixins accessible form definition win over those available in caller:

@variable: global;
@detached-ruleset: {
  //will use global variable, because it is accessible
  //from detached-ruleset definition
  variable: @variable; 
};

selector {
  @detached-ruleset();
  @variable: value; //variable defined in caller - will be ignored
}

compiles into:

selector {
  variable: global;
}