Skip to content

Supported Less Language

Mária Jurčovičová edited this page Apr 2, 2015 · 256 revisions

Less is an attempt to make css style sheets easier to read and maintain while keeping the syntax and behavior as close to css as possible. It is an extension of css and adds multiple dynamic features into standard style sheets. As any valid css file is also valid less file, no one has to rewrite all his sheets into an entirely different language.

This page describes less additions into css.

Escaping

Some browsers accept additional proprietary non-standard non-css syntax on top of the usual css. Less is build on top of standard css and therefore may not recognize it. You may also need to put an otherwise non-parseable value inside a variable and use it to dynamically build selector or other css part during compilation time (see selectors and media queries interpolation).

Escaping allows you to use any arbitrary string as property or variable value.

Simple example:

.weird-element {
  content: ~"^//* some horrible but needed css hack";
}

compiled css:

.weird-element {
  content: ^//* some horrible but needed css hack;
}

Variables

Variables are named values. Each number, color, string or any value can be assigned to a variable and the rest of the sheet then references variable instead of the original value. This makes style sheet maintenance much easier - use them right and each color or margin change will done on one place only. Searching through all style sheets to change all 'blue' into new main theme color is not needed anymore.

Variables can be used:

All in one example:

// declare three variables
@property-value: 1px;
@selector: ~"div.some-class"; // selector must be escaped or valid css value (this is escaped)
@media-query: ~"tablet"; // media query must be escaped or valid css value (this is escaped)
@property-name: box-shadow; // property name must be escaped or css value (this css value)

// use variables
@media @media-query { // in media query
  @{selector} { // in selector
    padding: @property-value; // as property value
    -moz-@{property-name}: shadow; // as property name
    in-string: "Padding was set to: @{property-value}"; // in string
  }
}

compiled css:

@media tablet {
  div.some-class {
    padding: 1px;
    -moz-box-shadow: shadow; 
    in-string: "Padding was set to: 1px";
  }
}

Operations & Functions

Less language supports four arithmetical operations plus '+', minus '-', multiplication '*', division '/' and parentheses '(' ')'. Use them to specify sizes and colors as relative to other sizes and colors. The evaluation of arithmetical expression is very intuitive, but their interaction with standard css can occasionally lead to subtle gotchas. If you run into one of them or just want to be warned in advance, read operations and quirks pages.

Less supports also several build-in functions.

Simple example:

// general theme settings
@themeColor: green; 
@themePadding: 3; 

// No matter how is the theme defined, code examples are going to be 
// darker then the rest of the page and have bigger padding.
pre {
  background-color: darken(@themeColor, 10%); // darker then usual color
  padding: (@themePadding+1) // bigger then usual padding
}

compiled css:

pre {
  background-color: #004d00;
  padding: 4;
}

Mixins

Standard css does not have an easy way to say: I want this ruleset to be just like that one, with this simple modification. If you need multiple rulesets with the same margin and padding, then you have to copy both margin and padding into all of them. When you decide to change the shared part, then you have to change it on all those copied places.

Mixins are solution to all these "code repetition" problems. Mixin in its most simple form is named group of css properties (declarations). You can include it into ruleset or another structure and all its properties are going to be copied there. Mixins features are described in Mixins page.

Simple example:

.mixin() { // declare very simple mixin
  margin: 2;
  padding: 1;
}
pre {
  .mixin(); // use the mixin
}

compiled css:

pre {
  margin: 2;
  padding: 1;
}

Detached Rulesets

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.

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

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

compiles into:

.top {
  background: red;
}

Properties Merging

Values for transforms, backgrounds, shadows and other "combinable" css properties can be defined inside separate declarations and then merged together using either + or +_ placed after property name. If less ruleset contains multiple declarations of the same property followed by one of these operators, compiled css will have only one property declaration with all their values collected into one list.

List values retain order in which they appeared in compiled css and are separated either by comma or by space. The values whose property was marked by + are preceded by comma and the values marked with +_ are preceded by space.

Simple example:

div { 
  box-shadow+: 40px 40px 5px #6f6f6f; // first light shadow 
  box-shadow+: 40px 40px 5px #222222; // second darker shadow - will be separated by comma
}

compiles into:

div { // div has both shadows
  box-shadow: 10px 10px 5px #6f6f6f, 40px 40px 5px #222222;
}

Details and more useful examples are shown on properties merging page.

Extend

If you have two selectors and want them to have exactly the same declarations in exactly the same order on exactly the same css locations, then you have to makes sure that every ruleset that has one of them contains also another one. Less extends keyword allows you to achieve this without having to manually copy any of these two selectors.

Simple example:

link:hover { // ruleset with target selector 
  color: blue;
}

.some-class:extend(link:hover) { // selector will be copied into ruleset having link:hover
  margin: 1 1 1 1;
}

compiled css:

link:hover, .some-class { // .some-class was added into this selectors list
  color: blue;
}

.some-class { // the extend keyword was stripped
  margin: 1 1 1 1;
}

Namespaces

Namespace encapsulate a group of mixins under common name. They have two purposes:

  • avoid naming conflicts in bigger projects,
  • encapsulate/isolate a group of mixins from outside world.

Nesting

A ruleset can be written inside another ruleset. The compiler then removes inner ruleset, places it right after the outer ruleset and combines their selectors together. 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 will not contain outer selector css properties.

Simple example:

.wish-list { // outer ruleset
   background-color: blue;
  .unavailable-item { // nested ruleset
     // special rules for wished but unavailable items
     background-color: red;
  }
}

compiled css:

.wish-list { // outer ruleset is unchanged
  color: blue;
}
.wish-list .unavailable-item { // special rules for wished but unavailable items
  color: red;
}

Guards on Css Styles

You can add guards to css styles. Guards are conditions specified after selector and use the same syntax as mixin guards. The style will used only if guard condition returns true.

@details: on;
.some > .complicated:selector when (@details=on) { // this style will show up in result
  display: block;
}
.some > .complicated:selector when (@details=off) { // this style will be ignored
  display:none;
}

compiles into:

.some > .complicated:selector {
  display: block;
}

Of course, style guards can be used in combination with mixins, nested rulesets and all other less language features. There is only one limitation: only single selector styles can have guards.

Directives Bubbling

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

Nested directives are "bubbled up" on top of stylesheet during compilation. Conditional directives e.g., @media, @documents and @supports also collect all selectors encountered on the way up and copy them inside themselves. Non-conditional directives are bubbled up without changes.

@media and @font-face directives inside ruleset:

.wish-list { 
  padding: 4;
  @media mobile { // mobile version uses smaller padding
    padding: 2;
  }
  @font-face {
    src: made-up-url;
  }
}

Both font-face and media directives are removed from .wish-list ruleset and placed on top of stylesheet. The .wish-list selector is also copied inside the media directive.

Compiled css:

// wish list styles on desktop or anything else that is not mobile are not affected
.wish-list { 
  padding: 4;
}
// wish list styles on mobile use special styles
@media mobile {
  // selectors encountered on the way up have been 
  // copied into the media clause 
  .wish-list { 
    padding: 2;
  }
}
@font-face { // selectors were not into the font-face clause
  src: made-up-url;
}

Therefore you do not have to maintain the same rulesets and selectors structures inside multiple directives.

Media Merging

Media merging happens when the compiler encounters media nested directly 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.

Simple example:

.wish-list { 
  padding: 4;
  @media mobile { // mobile version uses smaller padding
    padding: 2;
    @media (max-width: 80px) { // really small phones need to adjust also margin
      margin: 2;
   } 
  }
}

compiled css:

// wish list styles on desktop or anything else that is not mobile are not affected
.wish-list {
  padding: 4;
}
// wish list styles on mobile use special styles 
@media mobile {
  .wish-list { // selectors encountered on the way up have been copied into the media clause - as before
    padding: 2;
  }
}
// wish list styles on small mobiles use yet another styles 
@media mobile and (max-width: 80px) { // all media queries encountered on the way up have to be satisfied
  .wish-list { // selectors encountered on the way up have been copied into the media clause
    margin: 2;
  }
}

Import

Less import statements are able to import both css and less style sheets. However, imported css and less files are treated differently. While the compiler does not modify css import statements and outputs them as they were written, less import statements are processed. All mixins, namespaces, variables and anything else defined in imported less files are available to be used in importing sheet.

Embedded Scripting

Embedded or escaped script is code written in language other then less. Use it to add otherwise impossible calculations and logic into your less sheets. Contrary to other features explained here, it is not availale by default and has to be added as an extention. Any programming language can be embedded into less sheets compiled with less4j.

Less.js like javascript support can be added using less4j-javascript plugin. Example:

@content: "less symbol is < and more symbol is >";
.logaritmic-thing {
  // embedded JavaScript - escape < and > characters
  content: `@{content}.replace(/</g, '&lt;').replace(/>/g, '&gt;')`; 
}

compiles into:

.logaritmic-thing {
  content: "less symbol is &lt; and more symbol is &gt;";
}

Other Compiler Features

Less compilers performs few additional output optimizations. Those are described in Other Compiler Features wiki page.

Clone this wiki locally