1. Web Design
  2. HTML/CSS
  3. CSS

A Few Things You Might Not Know About LESS

Scroll to top
7 min read
This post is part of a series called LESS: Beyond the Basics.
A Deeper Look at LESS Mixins

It has been a long time since our last coverage of LESS. Last time we talked about it was in 2012, when LESS was still around version 1.2.0. At the time of this writing LESS is about to reach version 2.0, and there have been a number of improvements as well as a handful of added features in each iteration.

In this post, I’m going to highlight some of these features, some of which you might be blissfully unaware of.

Extending Selectors

To begin with, let’s talk about extend. Extend was one of the most requested features, since Sass and Stylus users have been enjoying it for some time. Use of the extend method allows us to produce leaner output by grouping selectors which share the same Mixins. It helps us to keep the style DRY and ultimately reduce the stylesheet size.

In Sass as well as Stylus, we would use the @extend directive to extend a mixin. LESS takes it differently; it uses its proprietary pseudo-class, :extend() and I think choosing to use a pseudo-class rather than an @ directive is a wise choice.

A standard CSS pseudo-class allows us to apply new style rules within an existing selector without completely overwriting the initial styles. The :extend() also uses a similar principle, including new styles into a new style rule where it is extended.

Assuming you have a mixin containing basic circle styles, like so:

1
.circle {
2
  border-radius: 50%;
3
}

You could use the :extend() pseudo-class to share the .circle styles within other selectors like so:

1
.circle {
2
  border-radius: 50%;
3
}
4
.button:extend(.circle) {
5
  position: absolute;
6
  top: 0;
7
  left: 0;
8
}

Alternatively, you could nest the :extend() pseudo-class with an & notation.

1
.circle {
2
  border-radius: 50%;
3
}
4
.button {
5
  &:extend(.circle);
6
  position: absolute;
7
  top: 0;
8
  left: 0;
9
}

This example will declare two .button selectors; the first one being tied with the .circle, therefore sharing the same border-radius:

1
.circle,
2
.button {
3
    border-radius: 50%;
4
}
5
.button {
6
    position: absolute;
7
    top: 0;
8
    left: 0;
9
}

Multiple Mixins

You can also extend multiple mixins within a single selector. In Sass and Stylus, we would declare each mixin within a separate @extend, while in LESS we declare the mixins in a single :extend() by separating each with a comma. Following up our previous example, we may add another selector defining the default brand color of the circle, for instance:

1
@gray: #ccc;
2
@gray-lighter: #f3f3f3;
3
.circle {
4
  border-radius: 50%;
5
}
6
.circle-default {
7
  background-color: @gray-lighter;
8
  border: 1px solid @gray;
9
}
10
.button {
11
  &:extend(.circle, .circle-default);
12
  position: absolute;
13
  top: 0;
14
  left: 0;
15
}

Which will be compiled into:

1
.circle,
2
.button {
3
  border-radius: 50%;
4
}
5
.circle-default,
6
.button {
7
  background-color: #f3f3f3;
8
  border: 1px solid #cccccc;
9
}
10
.button {
11
  position: absolute;
12
  top: 0;
13
  left: 0;
14
}

As you can see above, selectors that share the same styles from the extended mixins are declared together properly.

Extending Nested Selectors

Another thing that you should know is that the LESS extend method will only merge styles of the first selector. Styles which come from the child or nested selectors will not follow. Hence the.button class here:

1
@gray: #ccc;
2
@gray-lighter: #f3f3f3;
3
.parent {
4
    color: @gray;
5
    .child {
6
        color: @gray-lighter;   
7
    }
8
}
9
.button:extend(.parent) {
10
    font-family: Arial;
11
}

will not inherit the styles from the nested .child selector:

1
.parent,
2
.button {
3
  color: #cccccc;
4
}
5
.parent .child {
6
  color: #f3f3f3;
7
}
8
.button {
9
  font-family: Arial;
10
}

If you want the .button to share the styles from .child, you will have to tell LESS implicitly by including the selector within the brackets:

1
.button:extend(.parent .child) {
2
    font-family: Arial;
3
}

In this example, the output would be:

1
.parent,
2
.button {
3
  color: #cccccc;
4
}
5
.parent .child,
6
.button {
7
  color: #f3f3f3;
8
}
9
.button {
10
  font-family: Arial;
11
}

Personally, I like how LESS delivers the extend method. It gives great control over which selectors in a mixin to merge. Plan ahead as to how you want to declare the style rules of your website, and use extend whenever you think that a particular style rule should be shared through the selectors in the stylesheet.

Placeholder

Sass users will be familiar with the placeholder selector. A placeholder is similar to a class or an ID selector which contains a set of property declarations and also is used in tandem with an @extend directive. However, a placeholder is declared with a % sign and will never be compiled and output as CSS. So when the following  Sass code example is compiled:

1
%rounded {
2
  border-radius: 30px
3
}
4
.button-default {
5
  @extend %rounded;
6
}

...it will only output:

1
.button-default {
2
  border-radius: 30px;
3
}

LESS does not have a special selector like this, however, you can produce the same output by adding () at the end of the selector. For instance:

1
.rounded() {
2
  border-radius: 30px
3
}
4
.button-default {
5
  .rounded;
6
}

This method, in LESS, is officially known as Mixins as Functions.

More Import Options

LESS introduced several new options for importing external stylesheets. One of my favorite options is (reference). This tells LESS to not compile the stylesheet within the stylesheet where it is imported. LESS will treat the stylesheet with this option merely as a reference. Let’s look at our first example again.

Here we have basic styles to form a circle. Yet, this time, we save them in a separate mixins file, mixins.less.

1
@gray: #ccc;
2
@gray-lighter: #f3f3f3;
3
.circle {
4
  border-radius: 50%;
5
}
6
.circle-default {
7
  background-color: @gray-lighter;
8
  border: 1px solid @gray;
9
}

Now we import the mixins.less file into our main stylesheet using the (reference) command.

1
@import (reference) "mixins.less";

Then we can use the Mixins throughout the main stylesheet, for instance:

1
.button {
2
  .circle;
3
  .circle-default;
4
  position: absolute;
5
  top: 0;
6
  left: 0;
7
}

As mentioned, mixins contained in the mixins.less file will not be compiled into the main stylesheet. Hence the output will leave only the .button selector:

1
.button {
2
  border-radius: 50%;
3
  background-color: #f3f3f3;
4
  border: 1px solid #cccccc;
5
  position: absolute;
6
  top: 0;
7
  left: 0;
8
}

I find this particular option is useful (and I actually use it often) when using a hefty framework like Bootstrap.

1
@import (reference) "less/bootstrap/bootstrap.less";

With the above example, we will be able to reuse and extend some Bootstrap mixins and functions, whilst at the same time keeping the main stylesheet free from Bootstrap mess and clutter.

Turn CSS into LESS

Another option that I think you will also find it really useful is (less). We often incorporate libraries which are only available as vanilla .css like this:

1
@import "library.css";

Taken the above example, LESS will treat it simply as CSS. That means the stylesheet won’t be compiled, the output will stay just as it is (in our case: @import "library.css";), and the class selectors contained within will not be available as mixins; you will not be able to reuse or extend the selectors.

If you want it to behave more like a LESS stylesheet, you will have to declare the import statement as such by using the (less) option.

1
@import (less) "library.css";

Furthermore, if you want the stylesheet to be present just as reference, import it with a combination of (less) and (reference):

1
@import (less,reference) "library.css";

Variable Interpolation

Hugo Giraudel, in one of his Tuts+ articles, explained thoroughly the what, why, and how of Interpolation in Sass. LESS uses @{} to interpolate a variable, placing the variable name within the brackets, for instance:

1
@variable: 'value';
2
@{variable} //interpolated

We can use a variable in this way multiple times within a file; I often use this technique to specify file paths for images or fonts:

1
@path-img: 'assets/img';
2
.header {
3
  background-image: url('@{path-img}/bg.png');
4
}

You can also include interpolation within an @import statement, which (as I far I’m aware) is not yet possible in Sass.

1
// Variables
2
@path-less: 'src/less';
3
@path-img: 'assets/img';
4
 
5
// External Stylesheet
6
@import '@{path-less}/mixins.less';
7
 
8
// Styles
9
.header {
10
  background-image: url('@{path-img}/bg.png');
11
}

Or, perhaps use it for declaring selectors and properties:

1
@name: color;
2
.default-@{property} {
3
  @{property}: #0ee;
4
  background-@{property}: #999;
5
}

As you can see, the use and application of variable interpolation in LESS is extremely flexible.

Merging Property Values

The last LESS new feature that we are going to talk about here is merging. Merging makes it easy to deal with CSS properties which accept multiple values such as text-shadowbox-shadow, and transition.

Let’s assume you want to apply a transition effect to a button color and background. Perhaps you have a mixin containing the transition declaration for the text color.

1
.color-transition {
2
  transition: color 350ms;
3
}

Now let’s include it within another style rule with an existing transition declaration:

1
.button {
2
  .color-transition;
3
  transition: background-color 300ms;
4
}

In this case you would end up with two transition declarations in a single style rule:

1
.button {
2
  transition: color 350ms;
3
  transition: background-color 300ms;
4
}

The transition effect for the color won't function, as the latter will overwrite the first transition property. In order to make both the color and the background transitions work, you would have to include both values in a single declaration by delimiting each one with a comma. And this is where the merge feature comes in.

Add a plus sign after each property name, like so:

1
.color-transition() {
2
  transition+: color 350ms;
3
}
4
.button {
5
  .color-transition;
6
  transition+: background-color 300ms;
7
}

Now we would have the following output when it’s compiled:

1
.button {
2
  transition: color 350ms, background-color 300ms;
3
}

Conclusion

I think these — extend, mixins as functions, variable interpolation, import options, and merge — are very significant improvements to LESS. These features effectively help us produce more efficient and easily manageable styles. Maybe it’s time to revisit and refactor your old code!

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.