While web standards are awesome, they can also be rather — how shall we put this — standard. Backwards-compatibility, as noble a goal as it may be, holds back standards in many cases.
But, you don’t need to be tied to the standards and their shortcomings! Developers have always devised clever ways to work around the shortcomings of any platform. Android developers don’t necessarily need to use Java, iPhone developers aren’t stuck with Objective-C, and the web is no exception. As long as the final result is in web standard format, the browser won’t care if you coded your website in assembly, and entered it into your computer using a binary keypad.
CSS is awesome, but like all other web standards — heck like all standards ever devised — has its own shortcomings. It does not support simple constructs such as variables and functions.
You might wonder why one would even need variables and functions in CSS in the first place. After all, it isn’t a programming or scripting language.
The need for variables arises simply enough. Right now you have to repeat any value you have to use in multiple places. If you are writing the CSS code for the theme for a website, chances are you will have to use the same colour value in multiple places. It could be the background colour in one place, the border colour in another, and the text colour in yet another location. You have to repeat the same value in multiple places, which is bad enough and violates the DRY (Don’t Repeat Yourself) principle, but it gets worse if you have to change it later on.
As for functions, it is not unthinkable to want one part of you CSS code to be dependant on another. The width of the borders, and padding for some element might for example be dependent on the size of another element — for example a sidebar that has a margin that is 5% of its width.
Finally, while CSS is describing styles for HTML, which is a language that makes heavy use of nesting of tags, CSS itself cannot nest rules. Rather you have to provide the complete “path” or selector for the element you wish to style.
Enter LESS.
LESS is a language that extends the feature set of CSS to overcome some of its shortcomings, and make it a clearer cleaner language. We mentioned the above features partly because LESS has direct solutions for all of them, and more.
Best of all the syntax of LESS closely matches the syntax of CSS; so if you know CSS, learning LESS is breeze. In fact, any valid CSS is valid LESS code as well.
Of course LESS is not a standard, and browsers do not support the LESS syntax; so how does LESS work?
Well, the simplest way is to add LESS code to you file just as you would any other CSS code, but changing the rel = "stylesheet"
bit to rel = "stylesheet/less"
and adding JavaScript code that processes the LESS code and converts it to CSS.
This requires your users to download an additional JavaScript file, and then have it process the LESS code right in the browser.
Since the end-result is CSS in the browser, you might as well convert the LESS code to CSS on the server-side, and send that instead. For this you can use the LESS compiler based on node.js. Since the LESS code will be changing infrequently, you can generate the CSS code once, and use the resultant CSS code. If you modify the LESS code, simply regenerate the CSS code from it.
All this talk about LESS, and we have yet to see what it like. Let’s dive in.
As we mentioned before LESS is essentially just CSS with some sugar on top. There isn’t much to know about the syntax of LESS; however we can, should, and will take a look at how these features add on top of CSS.
Let’s take a look at some of the features of LESS and how they are implemented over the base CSS syntax.
Defining variables is very simple. All you need to do to declare one is to prefix ’@’ symbol before the variable name, and assign some value to it. Actually, since you cannot change a value once it has been assigned, these are technically constants.
In any case, let’s define a width for our columns:
@column-width: 100px;
Now wherever you wish to use this width, you can simply reference this variable instead.
.column { width: @column-width;}
You can even use basic math operations.
.column { width: @column-width; padding: @column-width * 5 / 100;}
As expected you can add, subtract, multiply, divide, and use brackets to define precedence. What’s more you can use these operations on other units such as %
, and em
, as well. In fact you can even operate on colours. You could for example set @theme-background: #45AA32;
and derive another colour from it as @theme-foreground: @theme-background #AA;
. This way you can set a base colour, and derive all the other colours in your theme from that using pre-set operations.
Another interesting feature of variables in LESS is that you can use two ’@’ symbols to call a variable referenced in its value! Let’s explain how this works. Say you have a variable named var1
:
@var1 = 10px;
And we have another variable called var2
, the value of which is set to the string var1
. As follows:
@var2 = 'var1';
Now, if you use two ’@’ symbols on var2
, it will first evaluate that as @var1
. So the following:
.margin { margin: @@var2;}
Will evaluate as:
.margin { margin: 10px;}
One major addition LESS makes to CSS is the ability to nest rules within one another. Let’s say we are dealing with a small widget that will appear in a sidebar. The widget has a title, and a list of links. Here is how you might do it with CSS:
.widget { background-color: black;}.widget .title { color: white; font-size: 16px;}.widget a { text-decoration: none; color: red;}.widget a:hover { color: white;}
All this can be represented in LESS as:
.widget { background-color: black; .title { color: white; font-size: 16px; } a { text-decoration: none; color: red; &:hover { color: white; } }}
It is a lot cleaner, concise and in line with how the elements in the HTML page are nested.
What if you needed two different elements to share some code? For example, you might want to include a standard pre-defined border in multiple rules. This too can be achieved quite simply:
.standard-border { border: solid 1px green;}
Now simply include this class name in any other class that needs to have a border. Such as:
.widget { .standard-border;}.showcase { .standard-border;}
Mixins are actually more flexible than we have described above. They can take parameters (which can have default values), they support different behaviours based on different input values, and even based on the number of parameters given.
Let’s create a parametric mixin that defines a widget. We will support changing the width and height of the widget, the border size, and the background and foreground colours:
.widget (@height, @width, @border: 1px, @back: black, @fore: red) { width: @width; height: @height; background-color: @back; color: @fore; border: solid @border @fore;}
Here by default the background colour is black, and the foreground / text colour is red. The border defaults to 1px in width. Since no defaults are specified for width and height, they need to be specified when using this mixin. Here is how you would use it:
.sidebar-widget { .widget (200px, 300px, 3px);}
This will evaluate to:
.sidebar-widget { width: 200px; height: 300px; background-color: black; color: red; border: solid 3px red;}
Now lets look at another example, one where we want to change the behaviour of a mixin based on the number of parameters supplied. We will create a parametric mixin for applying a border, where if one parameter is supplied, it is applied as the border width, and if two are supplied, one becomes the border width, and the other the border radius. What we need to do is simply create two mixins of the same name:
.bordered (@size) { border: solid @size black;}.bordered (@size, @radius) { border: solid @size black; border-radius: @radius;}
There are a number of other possibilities when it comes to parametric mixins. You can change the behaviour of a mixin based on the value of the parameters, or the type of parameters. For example, a mixin could alternate between white and black text based on whether the background colour provided by the user is light or dark. Let’s create a mixin that does just that:
.widget (@back-colour) when (lightness(@back-colour) >= 50%) { color: black;}.widget (@back-colour) when (lightness(@back-colour) < 50%) { color: white;}.widget (@back-colour) { background-color: @back-colour;}
Here the colour of the text is set according tot the lightness of the background colour. The third block, the one without the when
statement, is applied in both cases.
You can even check if the input value is colour, string, number, furthermore whether it is specified in pixels or percentages and base the style applied on that. Like the lightness
function above there is also iscolor
, isnumber
, isstring
, iskeyword
, isurl
, ispixel
, ispercentage
, and isem
.
To simplify working with numbers and colours, LESS provides a few functions. To deal with numbers LESS has the following: round
(rounding function), ceil
(ceiling function), floor
, percentage
(converts a number to its equivalent percentage).
More importantly, LESS provides a number of functions that operate on colours. These functions let you easily base one colour on another:
lighten(@colour, @percentage)
and darken(@colour, @percentage)
: these functions allow you to lighten or darken a colour by the specified percentage.saturate
and desaturate
: These take a colour and percentage parameter as above, and saturate / desaturate the provided colour by the specified percentage.fadein
, fadeout
and fade
: Again they take a colour and percentage. The first two fade in / out the specified colour by the provided amount, and the fade
function applies the specified percentage of transparency to the colour.spin
: This function takes a colour and an number, and increases / decreases the hue of the colour based on the number provided.mix
: This takes in two colours and mixes them up.hue
: returns the hue of the specified coloursaturation
: returns the saturation of the specified colourlightness
: returns the lightness of the specified colouralpha
: returns the alpha of the specified colour.
Its easy to see how powerful this can be. If a design is based on shades, variations or derivations of a few — maybe even one — basic colours, you can specify all the theme colours in one place, and then use these functions to derive any secondary colours. After that, change these variables, and the entire colour scheme of the site changes!
We haven’t even covered all of LESS’ functionality, and hopefully you can already see how awesome it is.
It’s important to know that there are alternatives out there that improve the web without breaking standards. LESS isn’t even the only alternative, there are others.
While LESS focusses on sticking to the CSS-style syntax, not all CSS alternatives do. In fact, if it is the CSS syntax that you dislike, LESS, for all the features it adds, isn’t of much help. SASS for example, has two syntaxes, one that uses indentation to demarcate blocks, and the other one uses a CSS-like syntax. Google’s Closure Stylesheets too have a different approach.
If you are a web developer, something like LESS should be part of your arsenal. There is little reason not to use it.
You can grab LESS from its page on GitHub and can read more about it on its site