Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

Advanced Less Coding

Save for later
  • 40 min read
  • 09 Feb 2015

article-image

In this article by Bass Jobsen, author of the book Less Web Development Cookbook, you will learn:

  • Giving your rules importance with the !important statement
  • Using mixins with multiple parameters
  • Using duplicate mixin names
  • Building a switch leveraging argument matching
  • Avoiding individual parameters to leverage the @arguments variable
  • Using the @rest... variable to use mixins with a variable number of arguments
  • Using mixins as functions
  • Passing rulesets to mixins
  • Using mixin guards (as an alternative for the if…else statements)
  • Building loops leveraging mixin guards
  • Applying guards to the CSS selectors
  • Creating color contrasts with Less
  • Changing the background color dynamically
  • Aggregating values under a single property

(For more resources related to this topic, see here.)


Giving your rules importance with the !important statement


The !important statement in CSS can be used to get some style rules always applied no matter where that rules appears in the CSS code. In Less, the !important statement can be applied with mixins and variable declarations too.

Getting ready


You can write the Less code for this recipe with your favorite editor. After that, you can use the command-line lessc compiler to compile the Less code. Finally, you can inspect the compiled CSS code to see where the !important statements appear. To see the real effect of the !important statements, you should compile the Less code client side, with the client-side compiler less.js and watch the effect in your web browser.

How to do it…

  1. Create an important.less file that contains the code like the following snippet:
    .mixin() {
    color: red;
    font-size: 2em;
    }
    p {
    &.important {
       .mixin() !important;
    }
    &.unimportant {
       .mixin();
    }
    }

  2. After compiling the preceding Less code with the command-line lessc compiler, you will find the following code output produced in the console:
    p.important {
    color: red !important;
    font-size: 2em !important;
    }
    p.unimportant {
    color: red;
    font-size: 2em;
    }

  3. You can, for instance, use the following snippet of the HTML code to see the effect of the !important statements in your browser:
    <p class="important"   style="color:green;font-size:4em;">important</p>
    <p class="unimportant"   style="color:green;font-size:4em;">unimportant</p>


    Your HTML document should also include the important.less and less.js files, as follows:

    <link rel="stylesheet/less" type="text/css"   href="important.less">
    <script src="less.js" type="text/javascript"></script>

  4. Finally, the result will look like that shown in the following screenshot: advanced-less-coding-img-0

How it works…


In Less, you can use the !important statement not only for properties, but also with mixins. When !important is set for a certain mixin, all properties of this mixin will be declared with the !important statement. You can easily see this effect when inspecting the properties of the p.important selector, both the color and size property got the !important statement after compiling the code.

There's more…


You should use the !important statements with care as the only way to overrule an !important statement is to use another !important statement. The !important statement overrules the normal CSS cascading, specificity rules, and even the inline styles. Any incorrect or unnecessary use of the !important statements in your Less (or CCS) code will make your code messy and difficult to maintain.

In most cases where you try to overrule a style rule, you should give preference to selectors with a higher specificity and not use the !important statements at all.

With Less V2, you can also use the !important statement when declaring your variables. A declaration with the !important statement can look like the following code:

@main-color: darkblue !important;

Using mixins with multiple parameters


In this section, you will learn how to use mixins with more than one parameter.

Getting ready


For this recipe, you will have to create a Less file, for instance, mixins.less. You can compile this mixins.less file with the command-line lessc compiler.

How to do it…

  1. Create the mixins.less file and write down the following Less code into it:
    .mixin(@color; @background: black;) {
    background-color: @background;
    color: @color;
    }
    div {
    .mixin(red; white;);
    }

  2. Compile the mixins.less file by running the command shown in the console, as follows:
    lessc mixins.less

  3. Inspect the CSS code output on the console, and you will find that it looks like that shown, as follows:
    div {
    background-color: #ffffff;
    color: #ff0000;
    }

How it works…


In Less, parameters are either semicolon-separated or comma-separated. Using a semicolon as a separator will be preferred because the usage of the comma will be ambiguous. The comma separator is not used only to separate parameters, but is also used to define a csv list, which can be an argument itself.

The mixin in this recipe accepts two arguments. The first parameter sets the @color variable, while the second parameter sets the @background variable and has a default value that has been set to black. In the argument list, the default values are defined by writing a colon behind the variable's name, followed by the value. Parameters with a default value are optional when calling the mixins. So the .color mixin in this recipe can also be called with the following line of code:

.mixin(red);


Because the second argument has a default value set to black, the .mixin(red); call also matches the .mixin(@color; @background:black){} mixin, as described in the Building a switch leveraging argument matching recipe.

Only variables set as parameter of a mixin are set inside the scope of the mixin. You can see this when compiling the following Less code:

.mixin(@color:blue){
color2: @color;
}
@color: red;
div {
color1: @color;
.mixin;
}


The preceding Less code compiles into the following CSS code:

div {
color1: #ff0000;
color2: #0000ff;
}


As you can see in the preceding example, setting @color inside the mixin to its default value does not influence the value of @color assigned in the main scope. So lazy loading is applied on only variables inside the same scope; nevertheless, you will have to note that variables assigned in a mixin will leak into the caller. The leaking of variables can be used to use mixins as functions, as described in the Using mixins as functions recipe.

There's more…


Consider the mixin definition in the following Less code:

.mixin(@font-family: "Helvetica Neue", Helvetica, Arial,   sans-serif;) {
font-family: @font-family;
}


The semicolon added at the end of the list prevents the fonts after the "Helvetica Neue" font name in the csv list from being read as arguments for this mixin. If the argument list contains any semicolon, the Less compiler will use semicolons as a separator. In the CSS3 specification, among others, the border and background shorthand properties accepts csv.

Also, note that the Less compiler allows you to use the named parameters when calling mixins. This can be seen in the following Less code that uses the @color variable as a named parameter:

.mixin(@width:50px; @color: yellow) {
width: @width;
color: @color;
}
span {
.mixin(@color: green);
}


The preceding Less code will compile into the following CSS code:

span {
width: 50px;
color: #008000;
}


Note that in the preceding code, #008000 is the hexadecimal representation for the green color. When using the named parameters, their order does not matter.

Using duplicate mixin names


When your Less code contains one or more mixins with the same name, the Less compiler compiles them all into the CSS code. If the mixin has parameters (see the Building a switch leveraging argument matching recipe) the number of parameters will also match.

Getting ready


Use your favorite text editor to create and edit the Less files used in this recipe.

How to do it…

  1. Create a file called mixins.less that contains the following Less code:
    .mixin(){
    height:50px;
    }
    .mixin(@color) {
    color: @color;
    }
     
    .mixin(@width) {
    color: green;
    width: @width;
    }
     
    .mixin(@color; @width) {
    color: @color;
    width: @width;
    }
     
    .selector-1 {
    .mixin(red);
    }
    .selector-2 {
    .mixin(red; 500px);
    }

  2. Compile the Less code from step 1 by running the following command in the console:
    lessc mixins.less

  3. After running the command from the previous step, you will find the following Less code output on the console:
    .selector-1 {
    color: #ff0000;
    color: green;
    width: #ff0000;
    }
    .selector-2 {
    color: #ff0000;
    width: 500px;
    }

How it works…


The .selector-1 selector contains the .mixin(red); call. The .mixin(red); call does not match the .mixin(){}; mixin as the number of arguments does not match. On the other hand, both .mixin(@color){}; and .mixin(@width){}; match the color. For this reason, these mixins will compile into the CSS code. The .mixin(red; 500px); call inside the .selector-2 selector will match only the .mixin(@color; @width){}; mixin, so all other mixins with the same .mixin name will be ignored by the compiler when building the .selector-2 selector.

The compiled CSS code for the .selector-1 selector also contains the width: #ff0000; property value as the .mixin(@width){}; mixin matches the call too. Setting the width property to a color value makes no sense in CSS as the Less compiler does not check for this kind of errors. In this recipe, you can also rewrite the .mixin(@width){}; mixin, as follows: .mixin(@width) when (ispixel(@width)){};.

There's more…


Maybe you have noted that the .selector-1 selector contains two color properties. The Less compiler does not remove duplicate properties unless the value also is the same. The CSS code sometimes should contain duplicate properties in order to provide a fallback for older browsers.

Building a switch leveraging argument matching


The Less mixin will compile into the final CSS code only when the number of arguments of the caller and the mixins match. This feature of Less can be used to build switches. Switches enable you to change the behavior of a mixin conditionally. In this recipe, you will create a mixin, or better yet, three mixins with the same name.

Getting ready


Use the command-line lessc compiler to evaluate the effect of this mixin. The compiler will output the final CSS to the console. You can use your favorite text editor to edit the Less code.

This recipe makes use of browser-vendor prefixes, such as the -ms-transform prefix. CSS3 introduced vendor-specific rules, which offer you the possibility to write some additional CSS, applicable for only one browser. These rules allow browsers to implement proprietary CSS properties that would otherwise have no working standard (and might never actually become the standard). To find out which prefixes should be used for a certain property, you can consult the Can I use database (available at http://caniuse.com/).

How to do it…

  1. Create a switch.less Less file, and write down the following Less code into it:
    @browserversion: ie9;
    .mixin(ie9; @degrees){
    transform:rotate(@degrees);
    -ms-transform:rotate(@degrees);
    -webkit-transform:rotate(@degrees);
    }
    .mixin(ie10; @degrees){
    transform:rotate(@degrees);
    -webkit-transform:rotate(@degrees);
    }
    .mixin(@_; @degrees){
    transform:rotate(@degrees);
    }
    div {
    .mixin(@browserversion; 70deg);
    }

  2. Compile the Less code from step 1 by running the following command in the console:
    lessc switch.less

  3. Inspect the compiled CSS code that has been output to the console, and you will find that it looks like the following code:
    div {
    -ms-transform: rotate(70deg);
    -webkit-transform: rotate(70deg);
    transform: rotate(70deg);
    }

  4. Finally, run the following command and you will find that the compiled CSS wll indeed differ from that of step 2:
    lessc --modify-var="browserversion=ie10" switch.less


    Now the compiled CSS code will look like the following code snippet:

    div {
    -webkit-transform: rotate(70deg);
    transform: rotate(70deg);
    }

How it works…


The switch in this recipe is the @browserversion variable that can easily be changed just before compiling your code. Instead of changing your code, you can also set the --modify-var option of the compiler.

Depending on the value of the @browserversion variable, the mixins that match will be compiled, and the other mixins will be ignored by the compiler. The .mixin(ie10; @degrees){} mixin matches the .mixin(@browserversion; 70deg); call only when the value of the @browserversion variable is equal to ie10. Note that the first ie10 argument of the mixin will be used only for matching (argument = ie10) and does not assign any value.

You will note that the .mixin(@_; @degrees){} mixin will match each call no matter what the value of the @browserversion variable is. The .mixin(ie9,70deg); call also compiles the .mixin(@_; @degrees){} mixin. Although this should result in the transform: rotate(70deg); property output twice, you will find only one. Since the property got exactly the same value twice, the compiler outputs the property only once.

There's more…


Not only switches, but also mixin guards, as described in the Using mixin guards (as an alternative for the if…else statements) recipe, can be used to set some properties conditionally.

Current versions of Less also support JavaScript evaluating; JavaScript code put between back quotes will be evaluated by the compiler, as can be seen in the following Less code example:

@string: "example in lower case";
p {
&:after { content: "`@{string}.toUpperCase()`";
}
}


The preceding code will be compiled into CSS, as follows:

p:after {
content: "EXAMPLE IN LOWER CASE";
}


When using client-side compiling, JavaScript evaluating can also be used to get some information from the browser environment, such as the screen width (screen.width), but as mentioned already, you should not use client-side compiling for production environments.

Because you can't be sure that future versions of Less still support JavaScript evaluating, and alternative compilers not written in JavaScript cannot evaluate the JavaScript code, you should always try to write your Less code without JavaScript.

Avoiding individual parameters to leverage the @arguments variable


In the Less code, the @arguments variable has a special meaning inside mixins. The @arguments variable contains all arguments passed to the mixin. In this recipe, you will use the @arguments variable together with the the CSS url() function to set a background image for a selector.

Getting ready


You can inspect the compiled CSS code in this recipe after compiling the Less code with the command-line lessc compiler. Alternatively, you can inspect the results in your browser using the client-side less.js compiler. When inspecting the result in your browser, you will also need an example image that can be used as a background image. Use your favorite text editor to create and edit the Less files used in this recipe.

How to do it…

  1. Create a background.less file that contains the following Less code:
    .background(@color; @image; @repeat: no-repeat; @position:   top right;)
    {
    background: @arguments;
    }
     
    div {
    .background(#000; url("./images/bg.png"));
    width:300px;
    height:300px;
    }

  2. Finally, inspect the compiled CSS code, and you will find that it will look like the following code snippet:
    div {
    background: #000000 url("./images/bg.png") no-repeat top     right;
    width: 300px;
    height: 300px;
    }

How it works…


The four parameters of the .background() mixin are assigned as a space-separated list to the @arguments variable. After that, the @arguments variable can be used to set the background property. Also, other CSS properties accept space-separated lists, for example, the margin and padding properties.

Note that the @arguments variable does not contain only the parameters that have been set explicit by the caller, but also the parameters set by their default value. You can easily see this when inspecting the compiled CSS code of this recipe. The .background(#000; url("./images/bg.png")); caller doesn't set the @repeat or @position argument, but you will find their values in the compiled CSS code.

Using the @rest... variable to use mixins with a variable number of arguments


As you can also see in the Using mixins with multiple parameters and Using duplicate mixin names recipes, only matching mixins are compiled into the final CSS code. In some situations, you don't know the number of parameters or want to use mixins for some style rules no matter the number of parameters. In these situations, you can use the special ... syntax or the @rest... variable to create mixins that match independent of the number of parameters.

Getting ready


You will have to create a file called rest.less, and this file can be compiled with the command-line lessc compiler. You can edit the Less code with your favorite editor.

How to do it…

  1. Create a file called rest.less that contains the following Less code:
    .mixin(@a...)
    {
    .set(@a) when (iscolor(@a)) {
       color: @a;
    }
    .set(@a) when (length(@a) = 2) {
       margin: @a;
    }
    .set(@a);
    }
    p{
    .mixin(red);
    }
    p {
    .mixin(2px;4px);
    }

  2. Compile the rest.less file from step 1 using the following command in the console:
    lessc rest.less

  3. Inspect the CSS code output to the console that will look like the following code:
    p {
    color: #ff0000;
    }
    p {
    margin: 2px 4px;
    }

How it works…


The special ... syntax (three dots) can be used as an argument for a mixin. Mixins with the ... syntax in their argument list match any number of arguments. When you put a variable name starting with an @ in front of the ... syntax, all parameters are assigned to that variable.

You will find a list of examples of mixins that use the special ... syntax as follows:

  • .mixin(@a; ...){}: This mixin matches 1-N arguments
  • .mixin(...){}: This mixin matches 0-N arguments; note that mixin() without any argument matches only 0 arguments
  • .mixin(@a: 1; @rest...){}: This mixin matches 0-N arguments; note that the first argument is assigned to the @a variable, and all other arguments are assigned as a space-separated list to @rest


Because the @rest... variable contains a space-separated list, you can use the Less built-in list function.

Using mixins as functions


People who are used to functional programming expect a mixin to change or return a value. In this recipe, you will learn to use mixins as a function that returns a value.

In this recipe, the value of the width property inside the div.small and div.big selectors will be set to the length of the longest side of a right-angled triangle based on the length of the two shortest sides of this triangle using the Pythagoras theorem.

Getting ready


The best and easiest way to inspect the results of this recipe will be compiling the Less code with the command-line lessc compiler. You can edit the Less code with your favorite editor.

How to do it…

  1. Create a file called pythagoras.less that contains the following Less code:
    .longestSide(@a,@b)
    {
    @length: sqrt(pow(@a,2) + pow(@b,2));
    }
    div {
    &.small {
       .longestSide(3,4);
       width: @length;
    }
    &.big {
       .longestSide(6,7);
       width: @length;
    }
    }

  2. Compile the pythagoras.less file from step 1 using the following command in the console:
    lessc pyhagoras.less

  3. Inspect the CSS code output on the console after compilation and you will see that it looks like the following code snippet:
    div.small {
    width: 5;
    }
    div.big {
    width: 9.21954446;
    }

How it works…


Variables set inside a mixin become available inside the scope of the caller. This specific behavior of the Less compiler was used in this recipe to set the @length variable and to make it available in the scope of the div.small and div.big selectors and the caller.

As you can see, you can use the mixin in this recipe more than once. With every call, a new scope is created and both selectors get their own value of @length.

Also, note that variables set inside the mixin do not overwrite variables with the same name that are set in the caller itself. Take, for instance, the following code:

.mixin() {
@variable: 1;
}
.selector {
@variable: 2;
.mixin;
property: @variable;
}


The preceding code will compile into the CSS code, as follows:

.selector {
property: 2;
}

There's more…


Note that variables won't leak from the mixins to the caller in the following two situations:

  • Inside the scope of the caller, a variable with the same name already has been defined (lazy loading will be applied)
  • The variable has been previously defined by another mixin call (lazy loading will not be applied)

Passing rulesets to mixins


Since Version 1.7, Less allows you to pass complete rulesets as an argument for mixins. Rulesets, including the Less code, can be assigned to variables and passed into mixins, which also allow you to wrap blocks of the CSS code defined inside mixins. In this recipe, you will learn how to do this.

Getting ready


For this recipe, you will have to create a Less file called keyframes.less, for instance. You can compile this mixins.less file with the command-line lessc compiler. Finally, inspect the Less code output to the console.

How to do it…

  1. Create the keyframes.less file, and write down the following Less code into it:
    // Keyframes
    .keyframe(@name; @roules) {
    @-webkit-keyframes @name {
       @roules();
    }
    @-o-keyframes @name {
       @roules();
    }
    @keyframes @name {
       @roules();
    }
    }
    .keyframe(progress-bar-stripes; {
    from { background-position: 40px 0; }
    to   { background-position: 0 0; }
    });

  2. Compile the keyframes.less file by running the following command shown in the console:
    lessc keyframes.less

  3. Inspect the CSS code output on the console and you will find that it looks like the following code:
    @-webkit-keyframes progress-bar-stripes {
    from {
       background-position: 40px 0;
    }
    to {
       background-position: 0 0;
    }
    }
    @-o-keyframes progress-bar-stripes {
    from {
       background-position: 40px 0;
    }
    to {
       background-position: 0 0;
    }
    }
    @keyframes progress-bar-stripes {
    from {
       background-position: 40px 0;
    }
    to {
       background-position: 0 0;
    }
    }

  4. Unlock access to the largest independent learning library in Tech for FREE!
    Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
    Renews at £15.99/month. Cancel anytime

How it works…


Rulesets wrapped between curly brackets are passed as an argument to the mixin. A mixin's arguments are assigned to a (local) variable. When you assign the ruleset to the @ruleset variable, you are enabled to call @ruleset(); to "mixin" the ruleset.

Note that the passed rulesets can contain the Less code, such as built-in functions too. You can see this by compiling the following Less code:

.mixin(@color; @rules)
{
@othercolor: green;
@media (print) {
   @rules();
}
}
 
p {
.mixin(red; {color: lighten(@othercolor,20%);     background-color:darken(@color,20%);})
}


The preceding Less code will compile into the following CSS code:

@media (print) {
p {
   color: #00e600;
   background-color: #990000;
}
}


A group of CSS properties, nested rulesets, or media declarations stored in a variable is called a detached ruleset. Less offers support for the detached rulesets since Version 1.7.

There's more…


As you could see in the last example in the previous section, rulesets passed as an argument can be wrapped in the @media declarations too. This enables you to create mixins that, for instance, wrap any passed ruleset into a @media declaration or class. Consider the example Less code shown here:

.smallscreens-and-olderbrowsers(@rules)
{
.lt-ie9 & {
   @rules();
}
@media (min-width:768px) {
   @rules();
}
}
nav {
float: left;
width: 20%;
.smallscreens-and-olderbrowsers({
   float: none;
   width:100%;
});
}


The preceding Less code will compile into the CSS code, as follows:

nav {
float: left;
width: 20%;
}
.lt-ie9 nav {
float: none;
width: 100%;
}
@media (min-width: 768px) {
nav {
   float: none;
   width: 100%;
}
}


The style rules wrapped in the .lt-ie9 class can, for instance, be used with Paul Irish's <html> conditional classes technique or Modernizr. Now you can call the .smallscreens-and-olderbrowsers(){} mixin anywhere in your code and pass any ruleset to it. All passed rulesets get wrapped in the .lt-ie9 class or the @media (min-width: 768px) declaration now. When your requirements change, you possibly have to change only these wrappers once.

Using mixin guards (as an alternative for the if…else statements)


Most programmers are used to and familiar with the if…else statements in their code. Less does not have these if…else statements. Less tries to follow the declarative nature of CSS when possible and for that reason uses guards for matching expressions. In Less, conditional execution has been implemented with guarded mixins. Guarded mixins use the same logical and comparison operators as the @media feature in CSS does.

Getting ready


You can compile the Less code in this recipe with the command-line lessc compiler. Also, check the compiler options; you can find them by running the lessc command in the console without any argument. In this recipe, you will have to use the –modify-var option.

How to do it…

  1. Create a Less file named guards.less, which contains the following Less code:
    @color: white;
    .mixin(@color) when (luma(@color) >= 50%) {
    color: black;
    }
    .mixin(@color) when (luma(@color) < 50%) {
    color: white;
    }
     
    p {
    .mixin(@color);
    }

  2. Compile the Less code in the guards.less using the command-line lessc compiler with the following command entered in the console:
    lessc guards.less

  3. Inspect the output written on the console, which will look like the following code:
    p {
    color: black;
    }

  4. Compile the Less code with different values set for the @color variable and see how to output change. You can use the command as follows:
    lessc --modify-var="color=green" guards.less


    The preceding command will produce the following CSS code:

    p {
     
    color: white;
     
    }

  5. Now, refer to the following command:
    lessc --modify-var="color=lightgreen" guards.less


    With the color set to light green, it will again produce the following CSS code:

    p {
     
    color: black;
     
    }


 

How it works…


The use of guards to build an if…else construct can easily be compared with the switch expression, which can be found in the programming languages, such as PHP, C#, and pretty much any other object-oriented programming language.

Guards are written with the when keyword followed by one or more conditions. When the condition(s) evaluates true, the code will be mixed in. Also note that the arguments should match, as described in the Building a switch leveraging argument matching recipe, before the mixin gets compiled.

The syntax and logic of guards is the same as that of the CSS @media feature.

A condition can contain the following comparison operators:

>, >=, =, =<, and <

Additionally, the keyword true is the only value that evaluates as true.


Two or more conditionals can be combined with the and keyword, which is equivalent to the logical and operator or, on the other hand, with a comma as the logical or operator. The following code will show you an example of the combined conditionals:

.mixin(@a; @color) when (@a<10) and (luma(@color) >= 50%) { }


The following code contains the not keyword that can be used to negate conditions:

.mixin(@a; @color) when not (luma(@color) >= 50%) { }

There's more…


Inside the guard conditions, (global) variables can also be compared. The following Less code example shows you how to use variables inside guards:

@a: 10;
.mixin() when (@a >= 10) {}


The preceding code will also enable you to compile the different CSS versions with the same code base when using the modify-var option of the compiler. The effect of the guarded mixin described in the preceding code will be very similar with the mixins built in the Building a switch leveraging argument matching recipe.

Note that in the preceding example, variables in the mixin's scope overwrite variables from the global scope, as can be seen when compiling the following code:

@a: 10;
.mixin(@a) when (@a < 10) {property: @a;}
selector {
.mixin(5);
}


The preceding Less code will compile into the following CSS code:

selector {
property: 5;
}


When you compare guarded mixins with the if…else constructs or switch expressions in other programming languages, you will also need a manner to create a conditional for the default situations. The built-in Less default() function can be used to create such a default conditional that is functionally equal to the else statement in the if…else constructs or the default statement in the switch expressions. The default() function returns true when no other mixins match (matching also takes the guards into account) and can be evaluated as the guard condition.

Building loops leveraging mixin guards


Mixin guards, as described besides others in the Using mixin guards (as an alternative for the if…else statements) recipe, can also be used to dynamically build a set of CSS classes. In this recipe, you will learn how to do this.

Getting ready


You can use your favorite editor to create the Less code in this recipe.

How to do it…

  1. Create a shadesofblue.less Less file, and write down the following Less code into it:
    .shadesofblue(@number; @blue:100%) when (@number > 0)
    {
     
    .shadesofblue(@number - 1, @blue - 10%);
     
    @classname: e(%(".color-%a",@number));
    @{classname} {
       background-color: rgb(0, 0, @blue);
       height:30px;
    }
    }
    .shadesofblue(10);

  2. You can, for instance, use the following snippet of the HTML code to see the effect of the compiled Less code from the preceding step:
    <div class="color-1"></div>
    <div class="color-2"></div>
    <div class="color-3"></div>
    <div class="color-4"></div>
    <div class="color-5"></div>
    <div class="color-6"></div>
    <div class="color-7"></div>
    <div class="color-8"></div>
    <div class="color-9"></div>
    <div class="color-10"></div>


    Your HTML document should also include the shadesofblue.less and less.js files, as follows:

    <link rel="stylesheet/less" type="text/css"   href="shadesofblue.less">

    <script src="less.js" type="text/javascript"></script>

  3. Finally, the result will look like that shown in this screenshot:
    advanced-less-coding-img-1

How it works…


The CSS classes in this recipe are built with recursion. The recursion here has been done by the .shadesofblue(){} mixin calling itself with different parameters. The loop starts with the .shadesofblue(10); call. When the compiler reaches the .shadesofblue(@number - 1, @blue – 10%); line of code, it stops the current code and starts compiling the .shadesofblue(){} mixin again with @number decreased by one and @blue decreased by 10 percent. The process will be repeated till @number < 1. Finally, when the @number variable becomes equal to 0, the compiler tries to call the .shadesofblue(0,0); mixin, which does not match the when (@number > 0) guard. When no matching mixin is found, the compiler stops, compiles the rest of the code, and writes the first class into the CSS code, as follows:

.color-1 {
background-color: #00001a;
height: 30px;
}


Then, the compiler starts again where it stopped before, at the .shadesofblue(2,20); call, and writes the next class into the CSS code, as follows:

.color-2 {
background-color: #000033;
height: 30px;
}


The preceding code will be repeated until the tenth class.

There's more…


When inspecting the compiled CSS code, you will find that the height property has been repeated ten times, too. This kind of code repeating can be prevented using the :extend Less pseudo class. The following code will show you an example of the usage of the :extend Less pseudo class:

.baseheight {
height: 30px;
}
.mixin(@i: 2) when(@i > 0) {
.mixin(@i - 1);
.class@{i} {
   width: 10*@i;
   &:extend(.baseheight);
}
}
.mixin();


Alternatively, in this situation, you can create a more generic selector, which sets the height property as follows:

div[class^="color"-] {
height: 30px;
}


Recursive loops are also useful when iterating over a list of values. Max Mikhailov, one of the members of the Less core team, wrote a wrapper mixin for recursive Less loops, which can be found at https://github.com/seven-phases-max. This wrapper contains the .for and .-each mixins that can be used to build loops. The following code will show you how to write a nested loop:

@import "for";
#nested-loops {
.for(3, 1); .-each(@i) {
   .for(0, 2); .-each(@j) {
     x: (10 * @i + @j);
   }
}
}


The preceding Less code will produce the following CSS code:

#nested-loops {
x: 30;
x: 31;
x: 32;
x: 20;
x: 21;
x: 22;
x: 10;
x: 11;
x: 12;
}


Finally, you can use a list of mixins as your data provider in some situations. The following Less code gives an example about using mixins to avoid recursion:

.data() {
.-("dark"; black);
.-("light"; white);
.-("accent"; pink);
}
 
div {
.data();
.-(@class-name; @color){
   @class: e(@class-name);
   &.@{class} {
     color: @color;
   }
}
}


The preceding Less code will compile into the CSS code, as follows:

div.dark {
color: black;
}
div.light {
color: white;
}
 
div.accent {
color: pink;
}

Applying guards to the CSS selectors


Since Version 1.5 of Less, guards can be applied not only on mixins, but also on the CSS selectors. This recipe will show you how to apply guards on the CSS selectors directly to create conditional rulesets for these selectors.

Getting ready


The easiest way to inspect the effect of the guarded selector in this recipe will be using the command-line lessc compiler.

How to do it…

  1. Create a Less file named darkbutton.less that contains the following code:
    @dark: true;
    button when (@dark){
    background-color: black;
    color: white;
    }

  2. Compile the darkbutton.less file with the command-line lessc compiler by entering the following command into the console:
    lessc darkbutton.less

  3. Inspect the CSS code output on the console, which will look like the following code:
    button {
    background-color: black;
    color: white;
    }

  4. Now try the following command and you will find that the button selector is not compiled into the CSS code:
    lessc --modify-var="dark=false" darkbutton.less

How it works…


The guarded CSS selectors are ignored by the compiler and so not compiled into the CSS code when the guard evaluates false. Guards for the CSS selectors and mixins leverage the same comparison and logical operators. You can read in more detail how to create guards with these operators in Using mixin guards (as an alternative for the if…else statements) recipe.

There's more…


Note that the true keyword will be the only value that evaluates true. So the following command, which sets @dark equal to 1, will not generate the button selector as the guard evaluates false:

lessc --modify-var="dark=1" darkbutton.less


The following Less code will give you another example of applying a guard on a selector:

@width: 700px;
div when (@width >= 600px ){
border: 1px solid black;
}


The preceding code will output the following CSS code:

div {
 
border: 1px solid black;
 
}


On the other hand, nothing will be output when setting @width to a value smaller than 600 pixels.

You can also rewrite the preceding code with the & feature referencing the selector, as follows:

@width: 700px;
div {
& when (@width >= 600px ){
   border: 1px solid black;
}
}


Although the CSS code produced of the latest code does not differ from the first, it will enable you to add more properties without the need to repeat the selector. You can also add the code in a mixin, as follows:

.conditional-border(@width: 700px) {
   & when (@width >= 600px ){
   border: 1px solid black;
}
width: @width;
}

Creating color contrasts with Less


Color contrasts play an important role in the first impression of your website or web application. Color contrasts are also important for web accessibility. Using high contrasts between background and text will help the visually disabled, color blind, and even people with dyslexia to read your content more easily.

The contrast() function returns a light (white by default) or dark (black by default) color depending on the input color. The contrast function can help you to write a dynamical Less code that always outputs the CSS styles that create enough contrast between the background and text colors. Setting your text color to white or black depending on the background color enables you to meet the highest accessibility guidelines for every color. A sample can be found at http://www.msfw.com/accessibility/tools/contrastratiocalculator.aspx, which shows you that either black or white always gives enough color contrast.

When you use Less to create a set of buttons, for instance, you don't want some buttons with white text while others have black text. In this recipe, you solve this situation by adding a stroke to the button text (text shadow) when the contrast ratio between the button background and button text color is too low to meet your requirements.

Getting ready


You can inspect the results of this recipe in your browser using the client-side less.js compiler. You will have to create some HTML and Less code, and you can use your favorite editor to do this. You will have to create the following file structure:

advanced-less-coding-img-2

How to do it…

  1. Create a Less file named contraststrokes.less, and write down the following Less code into it:
    @safe: green;
    @danger: red;
    @warning: orange;
    @buttonTextColor: white;
    @ContrastRatio: 7; //AAA, small texts
     
    .setcontrast(@backgroundcolor) when (luma(@backgroundcolor)   =< luma(@buttonTextColor)) and     
    (((luma(@buttonTextColor)+5)/     
    (luma(@backgroundcolor)+5)) < @ContrastRatio) {
    color:@buttonTextColor;
    text-shadow: 0 0 2px black;
    }
    .setcontrast(@backgroundcolor) when (luma(@backgroundcolor)   =< luma(@buttonTextColor)) and     
    (((luma(@buttonTextColor)+5)/     
    (luma(@backgroundcolor)+5)) >= @ContrastRatio) {
    color:@buttonTextColor;
    }
     
    .setcontrast(@backgroundcolor) when (luma(@backgroundcolor)   >= luma(@buttonTextColor)) and     
    (((luma(@backgroundcolor)+5)/     
    (luma(@buttonTextColor)+5)) < @ContrastRatio) {
    color:@buttonTextColor;
    text-shadow: 0 0 2px white;
    }
    .setcontrast(@backgroundcolor) when (luma(@backgroundcolor)   >= luma(@buttonTextColor)) and     
    (((luma(@backgroundcolor)+5)/     
    (luma(@buttonTextColor)+5)) >= @ContrastRatio) {
    color:@buttonTextColor;
    }
     
    button {
    padding:10px;
    border-radius:10px;
    color: @buttonTextColor;
    width:200px;
    }
     
    .safe {
    .setcontrast(@safe);
    background-color: @safe;
    }
     
    .danger {
    .setcontrast(@danger);
    background-color: @danger;
    }
     
    .warning {
    .setcontrast(@warning);
    background-color: @warning;
    }

  2. Create an HTML file, and save this file as index.html. Write down the following HTML code into this index.html file:
    <!DOCTYPE html>
    <html>
    <head>
       <meta charset="utf-8">
       <title>High contrast buttons</title>
       <link rel="stylesheet/less" type="text/css"       href="contraststrokes.less">
       <script src="less.min.js"       type="text/javascript"></script>
    </head>
    <body>
       <button style="background-color:green;">safe</button>
       <button class="safe">safe</button><br>
       <button style="background-color:red;">danger</button>
       <button class="danger">danger</button><br>
       <button style="background-color:orange;">     warning</button>
       <button class="warning">warning</button>
    </body>
    </html>

  3. Now load the index.html file from step 2 in your browser. When all has gone well, you will see something like what's shown in the following screenshot:advanced-less-coding-img-3


On the left-hand side of the preceding screenshot, you will see the original colored buttons, and on the right-hand side, you will find the high-contrast buttons.

How it works…


The main purpose of this recipe is to show you how to write dynamical code based on the color contrast ratio.

Web Content Accessibility Guidelines (WCAG) 2.0 covers a wide range of recommendations to make web content more accessible. They have defined the following three conformance levels:

    • Conformance Level A: In this level, all Level A success criteria are satisfied
    • Conformance Level AA: In this level, all Level A and AA success criteria are satisfied
    • Conformance Level AAA: In this level, all Level A, AA, and AAA success criteria are satisfied


If you focus only on the color contrast aspect, you will find the following paragraphs in the WCAG 2.0 guidelines.

    • 1.4.1 Use of Color: Color is not used as the only visual means of conveying information, indicating an action, prompting a response, or distinguishing a visual element. (Level A)
    • 1.4.3 Contrast (Minimum): The visual presentation of text and images of text has a contrast ratio of at least 4.5:1 (Level AA)
    • 1.4.6 Contrast (Enhanced): The visual presentation of text and images of text has a contrast ratio of at least 7:1 (Level AAA)


The contrast ratio can be calculated with a formula that can be found at http://www.w3.org/TR/WCAG20/#contrast-ratiodef:

(L1 + 0.05) / (L2 + 0.05)

In the preceding formula, L1 is the relative luminance of the lighter of the colors, and L2 is the relative luminance of the darker of the colors.

In Less, the relative luminance of a color can be found with the built-in luma() function. In the Less code of this recipe are the four guarded .setcontrast(){} mixins. The guard conditions, such as (luma(@backgroundcolor) =< luma(@buttonTextColor)) are used to find which of the @backgroundcolor and @buttonTextColor colors is the lighter one. Then the (((luma({the lighter color})+5)/(luma({the darker color})+5)) < @ContrastRatio) condition can, according to the preceding formula, be used to determine whether the contrast ratio between these colors meets the requirement (@ContrastRatio) or not. When the value of the calculated contrast ratio is lower than the value set by the @ContrastRatio, the text-shadow: 0 0 2px {color}; ruleset will be mixed in, where {color} will be white or black depending on the relative luminance of the color set by the @buttonTextColor variable.

There's more…


In this recipe, you added a stroke to the web text to improve the accessibility. First, you will have to bear in mind that improving the accessibility by adding a stroke to your text is not a proven method. Also, automatic testing of the accessibility (by calculating the color contrast ratios) cannot be done.

Other options to solve this issue are to increase the font size or change the background color itself. You can read how to change the background color dynamically based on color contrast ratios in the Changing the background color dynamically recipe.

When you read the exceptions of the 1.4.6 Contrast (Enhanced) paragraph of the WCAG 2.0 guidelines, you will find that large-scale text requires a color contrast ratio of 4.5 instead of 7.0 to meet the requirements of the AAA Level. Large-scaled text is defined as at least 18 point or 14 point bold or font size that would yield the equivalent size for Chinese, Japanese, and Korean (CJK) fonts. To try this, you could replace the text-shadow properties in the Less code of step 1 of this recipe with the font-size, 14pt, and font-weight, bold; declarations. After this, you can inspect the results in your browser again. Depending on, among others, the values you have chosen for the @buttonTextColor and @ContrastRatio variables, you will find something like the following screenshot:

advanced-less-coding-img-4

On the left-hand side of the preceding screenshot, you will see the original colored buttons, and on the right-hand side, you will find the high-contrast buttons. Note that when you set the @ContrastRatio variable to 7.0, the code does not check whether the larger font indeed meets the 4.5 contrast ratio requirement.

Changing the background color dynamically


When you define some basic colors to generate, for instance, a set of button elements, you can use the built-in contrast() function to set the font color. The built-in contrast() function provides the highest possible contrast, but does not guarantee that the contrast ratio is also high enough to meet your accessibility requirements. In this recipe, you will learn how to change your basic color automatically to meet the required contrast ratio.

Getting ready


You can inspect the results of this recipe in your browser using the client-side less.js compiler. Use your favorite editor to create the HTML and Less code in this recipe. You will have to create the following file structure:

advanced-less-coding-img-5

How to do it…

  1. Create a Less file named backgroundcolors.less, and write down the following Less code into it:
    @safe: green;
    @danger: red;
    @warning: orange;
    @ContrastRatio: 7.0; //AAA
    @precision: 1%;
    @buttonTextColor: black;
    @threshold: 43;
     
    .setcontrastcolor(@startcolor) when (luma(@buttonTextColor)   < @threshold) {
    .contrastcolor(@startcolor) when (luma(@startcolor) < 100     ) and (((luma(@startcolor)+5)/     
    (luma(@buttonTextColor)+5)) < @ContrastRatio) {
       .contrastcolor(lighten(@startcolor,@precision));
    }
    .contrastcolor(@startcolor) when (@startcolor =     color("white")),(((luma(@startcolor)+5)/     
    (luma(@buttonTextColor)+5)) >= @ContrastRatio) {
       @contrastcolor: @startcolor;
    }
    .contrastcolor(@startcolor);
    }
     
    .setcontrastcolor(@startcolor) when (default()) {
    .contrastcolor(@startcolor) when (luma(@startcolor) < 100     ) and (((luma(@buttonTextColor)+5)/     
    (luma(@startcolor)+5)) < @ContrastRatio) {
       .contrastcolor(darken(@startcolor,@precision));
    }
    .contrastcolor(@startcolor) when (luma(@startcolor) = 100     
    ),(((luma(@buttonTextColor)+5)/(luma(@startcolor)+5))       
    >= @ContrastRatio) {
       @contrastcolor: @startcolor;
    }
    .contrastcolor(@startcolor);
    }
     
    button {
    padding:10px;
    border-radius:10px;
    color:@buttonTextColor;
    width:200px;
    }
     
    .safe {
    .setcontrastcolor(@safe);
    background-color: @contrastcolor;
    }
     
    .danger {
    .setcontrastcolor(@danger);
    background-color: @contrastcolor;
    }
     
    .warning {
    .setcontrastcolor(@warning);
    background-color: @contrastcolor;
    }

  2. Create an HTML file and save this file as index.html. Write down the following HTML code into this index.html file:
    <!DOCTYPE html>
    <html>
    <head>
       <meta charset="utf-8">
       <title>High contrast buttons</title>
     
       <link rel="stylesheet/less" type="text/css"       href="backgroundcolors.less">
       <script src="less.min.js"       type="text/javascript"></script>
    </head>
    <body>
       <button style="background-color:green;">safe</button>
       <button class="safe">safe</button><br>
       <button style="background-color:red;">danger</button>
       <button class="danger">danger</button><br>
       <button style="background-color:orange;">warning     </button>
       <button class="warning">warning</button>
    </body>
    </html>

  3. Now load the index.html file from step 2 in your browser. When all has gone well, you will see something like the following screenshot:advanced-less-coding-img-6


On the left-hand side of the preceding figure, you will see the original colored buttons, and on the right-hand side, you will find the high contrast buttons.

How it works…


The guarded .setcontrastcolor(){} mixins are used to determine the color set depending upon whether the @buttonTextColor variable is a dark color or not. When the color set by @buttonTextColor is a dark color, with a relative luminance below the threshold value set by the @threshold variable, the background colors should be made lighter. For light colors, the background colors should be made darker.

Inside each .setcontrastcolor(){} mixin, a second set of mixins has been defined. These guarded .contrastcolor(){} mixins construct a recursive loop, as described in the Building loops leveraging mixin guards recipe. In each step of the recursion, the guards test whether the contrast ratio that is set by the @ContrastRatio variable has been reached or not. When the contrast ratio does not meet the requirements, the @startcolor variable will darken or lighten by the number of percent set by the @precision variable with the built-in darken() and lighten() functions. When the required contrast ratio has been reached or the color defining the @startcolor variable has become white or black, the modified color value of @startcolor will be assigned to the @contrastcolor variable. The guarded .contrastcolor(){} mixins are used as functions, as described in the Using mixins as functions recipe to assign the @contrastcolor variable that will be used to set the background-color property of the button selectors.

There's more…


A small value of the @precision variable will increase the number of recursions (possible) needed to find the required colors as there will be more and smaller steps needed. With the number of recursions also, the compilation time will increase. When you choose a bigger value for @precision, the contrast color found might differ from the start color more than needed to meet the contrast ratio requirement.

When you choose, for instance, a dark button text color, which is not black, all or some base background colors will be set to white. The chances of finding the highest contrast for white increase for high values of the @ContrastRatio variable. The recursions will stop when white (or black) has been reached as you cannot make the white color lighter. When the recursion stops on reaching white or black, the colors set by the mixins in this recipe don't meet the required color contrast ratios.

Aggregating values under a single property


The merge feature of Less enables you to merge property values into a list under a single property. Each list can be either space-separated or comma-separated. The merge feature can be useful to define a property that accepts a list as a value. For instance, the background accepts a comma-separated list of backgrounds.

Getting ready


For this recipe, you will need a text editor and a Less compiler.

How to do it…

  1. Create a file called defaultfonts.less that contains the following Less code:
    .default-fonts() {
    font-family+: Helvetica, Arial, sans-serif;
    }
    p {
    font-family+: "Helvetica Neue";
    .default-fonts();
    }

  2. Compile the defaultfonts.less file from step 1 using the following command in the console:
    lessc defaultfonts.less

  3. Inspect the CSS code output on the console after compilation and you will see that it looks like the following code:
    p {
    font-family: "Helvetica Neue", Helvetica, Arial, sans-   serif;
    }

How it works…


When the compiler finds the plus sign (+) before the assignment sign (:), it will merge the values into a CSV list and will not create a new property into the CSS code.

There's more…


Since Version 1.7 of Less, you can also merge the property's values separated by a space instead of a comma. For space-separated values, you should use the +_ sign instead of a + sign, as can be seen in the following code:

.text-overflow(@text-overflow: ellipsis) {
text-overflow+_ : @text-overflow;
}
p, .text-overflow {
.text-overflow();
text-overflow+_ : ellipsis;
}


The preceding Less code will compile into the CSS code, as follows:

p,
.text-overflow {
text-overlow: ellipsis ellipsis;
}


Note that the text-overflow property doesn't force an overflow to occur; you will have to explicitly set, for instance, the overflow property to hidden for the element.

Summary


This article walks you through the process of parameterized mixins and shows you how to use guards. A guard can be used with as if-else statements and make it possible to construct interactive loops in Less.

Resources for Article:


Further resources on this subject: