Quick Introduction to LESS

These are some of the features LESS is offering you:

Creating variables

You can save a value on a variable and use it later, quite useful to set colors:

@myCustomColor: #567;
@primaryColor: blue;
@secondaryColor: darkblue;

.myCustomStyle{
    background: @myCustomColor;
}
.anotherStyle{
    color: 'myCustomColor';
}

Notice you can add the variable by setting it directly or by setting its name.

Mixins

If having a variable value is not enough, you can group a few properties and create an inheritable style (called mixin):

.fontTitle{
    font-family:Fira Sans;
    font-weight:700;
    font-style: italic;
}
.fontText {
    font-family:Cabin;
    font-style: normal;
    font-weight:normal;
}
.fontEmphasized {
    font-family:Lora;
    font-weight:700;
    font-style: italic;
}

h1, h2, h3, h4, h5, h6 {
    .fontTitle;
}

p, li {
    .fontText;
}

.someClassOutThere{
    .fontTitle;
    ...
}

You can add the parenthesis to a mixin or not, doing so is optional, but on the generated .css file mixins with parenthesis will not be displayed while mixins without them will:

.myOutputtedMixin{
    color: green;
}
.myNonOutputtedMixin(){
    color: red;
}

// The generated.css file will have:
.myOutputtedMixin{
    color: green;
}

That means that you can’t reuse parenthesized mixins after generating the css file.

Parametric Mixins

These allow you to set a value so that several styles will be set at once like a mixin but using that value:

.makeSquare(@size){
    height: @size;
    width:  @size;
    display:block;
}
.setBorderRadius(@radius){
    -webkit-border-radius: @radius;
    -moz-border-radius: @radius;
    border-radius: @radius;
}

.myCustomStyle{
    .makeSquare(200px);
    .setBorderRadius(5px);
}

Parameter default value

You can also add a default value to a parametric mixin:

.setBorderRadius(@radius: 5px) {
  -webkit-border-radius: @radius;
     -moz-border-radius: @radius;
          border-radius: @radius;
}

#header {
  .setBorderRadius; // No need to set a value, default one is 5px.
}

Multiple and Named Parameters

You can add more than one parameter and also use the parameter name when calling the mixin so that you can use any calling order:

.myMixin(@color: black; @margin: 10px; @padding: 20px) {
  color: @color;
  margin: @margin;
  padding: @padding;
}

.class1 {
  .myMixin(@margin: 20px; @color: #33acfe);
}

.class2 {
  .myMixin(#efca44; @padding: 40px);
}

Namespaces

Just because you may be worried that your mixins may conflict any other stylesheet you can add a namespace to generate a library-like space for your mixins:

#myLibrary{
    .myFirstMixin{ ... }
    .mySecondMixin{ ... }
    ...
}

// This class will "inherit" the mixin inside our library, there are 4 ways of doing that:
.myCustomClass{
    // all do the same thing
    #myLibrary > .myFirstMixin;
    #myLibrary > .myFirstMixin();
    #myLibrary.myFirstMixin;
    #myLibrary.myFirstMixin();
}

Operations

You can also adapt a value inline by making some simple operation:

@baseFontSize: 14px;
@basePadding: 5px;
@primaryColor: "#FF0";
@secondaryColor: @primaryColor - "222"; //Darkening a bit whatever color is the main.

.customTitle{
    font-size: @baseFontSize * 2;
    padding-bottom: (@basePadding * 1.5) + 10;
    color: @primaryColor - "0F0"; //removing green becomes red.
}

.MakeRectangle(@side){
    height: @side;
    width:  @side * 3;
    display:block;
}

.myRectangle{
    .makeRectangle(100px);
}

Color Functions

Yes, you can use operations over colors, but calculating stuff on them isn’t an easy task for those of us not used to play with them. So LESS already includes some functions to make color calculations:

lighten(@color, 10%);     // return a color which is 10% *lighter* than @color
darken(@color, 10%);      // return a color which is 10% *darker* than @color

saturate(@color, 10%);    // return a color 10% *more* saturated than @color
desaturate(@color, 10%);  // return a color 10% *less* saturated than @color

fadein(@color, 10%);      // return a color 10% *less* transparent than @color
fadeout(@color, 10%);     // return a color 10% *more* transparent than @color
fade(@color, 50%);        // return @color with 50% transparency

spin(@color, 10);         // return a color with a 10 degree larger in hue than @color
spin(@color, -10);        // return a color with a 10 degree smaller hue than @color

mix(@color1, @color2);    // return a mix of @color1 and @color2

Other Functions

Not only color functions, but also some Math ones in case you need to make more complex operations like round(), ceil(), floor() and percentage().
Also some functions to check the type of a value: iscolor, isnumber, iskeyword, isurl, ispixel, ispercentage, isem, isunit.

Mixin guards

These work as conditional mixins that will add different values depending on the conditions being met or not:

@primarycolor: "#233300";

.myMixin (@a) when (lightness(@a) >= 50%) {
  background-color: black;
}
.myMixin (@a) when (lightness(@a) < 50%) {
  background-color: white;
}
.myMixin (@a) {
  color: @a;
}

.myClass{
    myMixin(@primaryColor);
}

That will give our class the primary color as the text color and a background depending on how much light the color is. You can see more about these guards at the official documentation.

Default value and other comparison operators

Just to note you can also do this:

.myMixin (@a) when (default()) { ... } // matches only when no other condition does.
.myMixin (@a; @b: 0) when (isnumber(@b)) { ... } // Using the type checking functions
.myMixin (@a) when (isnumber(@a)) and (@a > 0) { ... } // Adding more than one condition
.myMixin (@a; @b) when (@a > @b) { width: @a } // Comparing arguments between them
.myMixin (@b) when not (@b > 0) { ... } // Negative condition

// Conditioning on external variables (I mean outside the mixin)
@media: mobile;
.myMixin (@a) when (@media = mobile) { ... }

Recursive mixins/functions

You can also generate some recursivity, for example:

@baseHeight: 1px;
.setRelativeHeight(@screenHeight, @minHeightDiff, @maxHeightDiff) when (@screenHeight < 1800) {

    @media (min-height: (@baseHeight * @screenHeight)) {
        min-height: @baseHeight * (@screenHeight - @minHeightDiff);
        max-height: @baseHeight * (@screenHeight - @maxHeightDiff);
    }
    .setRelativeHeight(@screenHeight + 20, @minHeightDiff, @maxHeightDiff);
}

Be care on not making an infinite loop, to avoid that, just set a “when” to set the limit. You can also use the parent symbol (see below) to make some recursive styling to nested elements, like setting more or less padding depending on level. Just as an idea.

Parent Selector

The “&” operator represents the parent selectors of a nested rule and is most commonly used when applying a modifying class or pseudo-class to an existing selector:

a {
  color: blue;
  &:hover {
    color: green;
  }
}

“&” may appear more than once within a selector. This makes it possible to repeatedly refer to a parent selector without repeating its name.

.link {
  & + & {
    color: red;
  }

  & & {
    color: green;
  }

  && {
    color: blue;
  }

  &, &ish {
    color: cyan;
  }
}

Note that & represents all parent selectors (not just the nearest ancestor)

// So the following example:
.grand {
  .parent {
    & > & {
      color: red;
    }
  }
}

// Results in:
.grand .parent > .grand .parent {
  color: red;
}

Combinatorial explosion

“&” can also be used to generate every possible permutation of selectors in a comma separated list:

p, a, ul, li {
border-top: 2px dotted #366;
  & + & {
      border-top: 0;
  }
}

This expands to all possible (16) combinations of the specified elements:

p,
a,
ul,
li {
  border-top: 2px dotted #366;
}
p + p,
p + a,
p + ul,
p + li,
a + p,
a + a,
a + ul,
a + li,
ul + p,
ul + a,
ul + ul,
ul + li,
li + p,
li + a,
li + ul,
li + li {
  border-top: 0;
}

Importing

You can also use @import to include more files into your compiles .less one, this allows to divide your styling into areas and also modularize it and include only the required ones depending on the project/section you are going to display. Contrary to standard CSS, @import doesn’t need to be declared at the top but can be declared at any place with LESS. Also, there are different directives that you can use when making an import:

@import (keyword) "filename"; // where keyword is one of the directives

The following import directives have been implemented:

  • reference: use a Less file but do not output it
  • inline: include the source file in the output but do not process it
  • less: treat the file as a Less file, no matter what the file extension
  • css: treat the file as a CSS file, no matter what the file extension
  • once: only include the file once (this is default behavior)
  • multiple: include the file multiple times

Leave a Reply

Close Bitnami banner
Bitnami