In recent years, CSS has matured into a very powerful way to style web pages. It’s now possible to create a website’s look almost entirely in CSS, with minimal use of images.
This is great, but one drawback is that CSS stylesheets are becoming longer, more complex, and harder to manage. It’s not uncommon for a typical stylesheet to run into hundreds of lines of code, with a large number of interdependent rules.
For this reason, various dynamic stylesheet languages are starting to spring up. These allow you to write your CSS rules using a more flexible, powerful language that is then turned into regular CSS for the browser to interpret.
In this article you’ll learn how to use LESS, an increasingly popular dynamic CSS language that you can use to streamline your CSS coding, saving you time and effort.
What is LESS?
LESS is a dynamic stylesheet language that extends the standard CSS syntax. This means that you can create a LESS stylesheet using regular CSS, and just add LESS code to the stylesheet as and when you need it.
The standard LESS compiler is written in JavaScript, so you can just include it in your web pages along with your LESS stylesheet. The compiler then converts your LESS code into CSS on the fly when the browser loads the page. There are also compilers available in other languages, as we’ll see later.
LESS is easy to understand, install and use. It gives you lots of useful features, including:
- Variables and mixins, which let you create values and rules once, then reuse them throughout your stylesheet
- Nested rules — these can save you a lot of coding, and they make inheritance clearer
- Operators and functions, which let you create CSS properties mathematically
- Namespaces for grouping and encapsulating variables and mixins
- … and lots more!
Installing LESS in your web page
Using LESS is easy:
- Download the
less.js
JavaScript file from the LESS website. - Save the file somewhere in your website, such as the document root.
- Write your LESS stylesheet and save it in a file called, for example,
style.less
in your document root. - Include
less.js
and your LESS stylesheet file in thehead
section of your web pages:<link rel="stylesheet/less" type="text/css" href="style.less"> <script src="less-1.0.41.min.js" type="text/javascript"></script>
Make sure the link to your LESS stylesheet is before the
less.js
include in yourhead
section.
That’s it! When your page loads, the less.js
script runs automatically, converting your LESS stylesheet rules into regular CSS rules, which are then processed by the browser.
Now that you know how to install LESS, what can you do with it? In the following sections we’ll explore the features of the LESS language, and see how to use them.
Reusing values with variables
The first LESS feature we’ll look at is variables. These let you create a value once, then reuse that value within as many CSS declarations as you like.
To create a variable, you use the following syntax:
@variable-name: value;
For example, you can create a variable to hold one of the main colours that you use on your website. It’s then easy to use that colour throughout your stylesheet:
@mainColour: #309296; body { color: @mainColour; } blockquote { border: 2px solid @mainColour; }
This is equivalent to writing the following CSS:
body { color: #309296; } blockquote { border: 2px solid #309296; }
Reusing rules with mixins
As well as reusing values with variables, you can reuse whole blocks of CSS throughout your stylesheet. These are called mixins.
Any ruleset that uses a class, id or element selector can be “mixed into” any other ruleset. You mix a ruleset into another simply by including the first ruleset’s selector within the second ruleset. Here’s an example:
.roundedBox { border: 1px solid #309296; background-color: #eee; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; padding: 10px; } blockquote { font-size: 1.5em; .roundedBox; } .promo { width: 10em; .roundedBox; }
This is equivalent to the following CSS:
.roundedBox { border: 2px solid #309296; background-color: #eee; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; padding: 10px; } blockquote { font-size: 1.5em; border: 2px solid #309296; background-color: #eee; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; padding: 10px; } .promo { width: 10em; border: 2px solid #309296; background-color: #eee; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; padding: 10px; }
You can also add parameters to mixins, making them behave more like functions. Let’s modify the above example so that the border radius and colour can be changed dynamically:
.roundedBox( @borderRadius, @borderColour ) { border: 2px solid @borderColour; background-color: #eee; -moz-border-radius: @borderRadius; -webkit-border-radius: @borderRadius; border-radius: @borderRadius; padding: 10px; } blockquote { font-size: 1.5em; .roundedBox( 5px, #6c6 ); } .promo { width: 10em; .roundedBox( 10px, #fa6 ); }
As you can see, we’ve added a couple of parameters to the .roundedBox
ruleset: @borderRadius
and @borderColour
. We use those values to define the border radius and colour inside the ruleset.
Then, when we use the mixin inside the blockquote
and .promo
rulesets, we specify different values for the parameters, adding a 5-pixel green border to blockquotes and a 10-pixel orange border to promo boxes.
You can also specify default values for mixin parameters. For example:
.roundedBox( @borderRadius: 5px, @borderColour: #6c6 ) { /* declarations here */ }
Writing concise CSS with nested rules
LESS lets you use nesting to write cascading rules more concisely. Consider the following rules for styling a navigation menu and its links:
ul#nav { list-style: none; } ul#nav li { display: inline; margin: 0; padding: 0; } ul#nav li a { color: #aaa; font-size: 1em; } ul#nav li a:hover { color: #000; }
This works fine, but there’s a lot of repetition in the selectors (ul#nav
, ul#nav li
, ul#nav li a
, ul#nav li a:hover
), and the inheritance isn’t all that clear.
By using nesting in LESS, we can rewrite the above CSS like this:
ul#nav { list-style: none; li { display: inline; margin: 0; padding: 0; a { color: #aaa; font-size: 1em; &:hover { color: #000; } } } }
The LESS compiler then converts the nested version to regular CSS code.
Not only is the nested version more concise, but it’s easier to see the cascade. For example, it’s obvious at a glance that all the rules relate to elements inside the ul#nav
unordered list.
By the way, notice the line:
&:hover { color: #000; }
The &
(ampersand) tells LESS not to put a space between the selector’s parent and the selector in the final CSS. This is handy when working with pseudo-classes such as :hover
. If you miss out the ampersand like this:
a { color: #aaa; font-size: 1em; :hover { color: #000; } }
…then LESS will produce the following CSS:
a { color: #aaa; font-size: 1em; } a :hover { color: #000; }
Notice that LESS has put a space between the a
and the :hover
, which isn’t what you want to happen.
Performing calculations using operators and functions
A really useful feature of LESS is the ability to use operators and functions to manipulate values. You can manipulate literal numbers, colour values and variables this way.
Here are the operators and functions you can use in LESS:
Operator / Function | Description |
---|---|
+, -, *, / |
Arithmetic operators |
lighten(@colour, x%) |
Returns the colour value @colour , lightened by x percent |
darken(@colour, x%) |
Returns the colour value @colour , darkened by x percent |
saturate(@colour, x%) |
Returns the colour value @colour , with saturation increased by x percent |
desaturate(@colour, x%) |
Returns the colour value @colour , with saturation decreased by x percent |
fadein(@colour, x%) |
Returns the colour value @colour , made x percent more opaque |
fadeout(@colour, x%) |
Returns the colour value @colour , made x percent more transparent |
spin(@colour, x) |
Returns the colour value @colour , with its hue shifted by x degrees on the colour wheel |
hue(@colour) |
Returns the hue component of the colour value @colour |
saturation(@colour) |
Returns the saturation component of the colour value @colour |
lightness(@colour) |
Returns the lightness component of the colour value @colour |
Here are some of the things you can do with operators and functions.
Example 1: Computing heading font sizes
We can set a variable to store the font size for level 1 headings, then compute the sizes for the other headings based on the level 1 value:
@h1Size: 5em; h1 { font-size: @h1Size; } h2 { font-size: @h1Size * .8; } h3 { font-size: @h1Size * .6; } h4 { font-size: @h1Size * .4; } h5 { font-size: @h1Size * .2; }
Example 2: Computing colours
Here’s another example — setting a dark brown base colour value for level 1 headings, then computing progressively lighter shades of brown for the other heading levels:
@mainColour: #631; h1 { color: @mainColour; } h2 { color: lighten(@mainColour, 10%); } h3 { color: lighten(@mainColour, 20%); } h4 { color: lighten(@mainColour, 30%); } h5 { color: lighten(@mainColour, 40%); }
Example 3: Computing container width
We can also use variables and arithmetic to compute the width of a container element to allow for border width and padding:
@outerWidth: 960px; @borderWidth: 10px; @padding: 10px; #container { width: @outerWidth - ( @borderWidth + @padding ) * 2; border: @borderWidth solid #999; padding: @padding; }
Grouping stuff using namespaces
You can group variables and mixins under a namespace to keep them separate from other rulesets. This can be handy if you have a lot of LESS rules or include multiple LESS stylesheets, and you want to avoid naming clashes.
To create a namespace, just wrap your rules in a new id selector:
#myNamespace {
.selector1 { ... }
#selector2 { ... }
}
Then you can reference the rules in the namespace using the child selector, >
:
#myNamespace > .selector1;
#myNamespace > #selector2;
For example, let’s encapsulate our container width example from the last section in a namespace called #articlePage
:
#articlePage { @outerWidth: 960px; @borderWidth: 10px; @padding: 10px; #containerStyle { width: @outerWidth - ( @borderWidth + @padding ) * 2; border: @borderWidth solid #999; padding: @padding; } }
We can now mix the entire #containerStyle
ruleset into a #container
rule to style our actual container, as follows:
#container { #articlePage > #containerStyle; }
How’s that for powerful!
CSS and LESS comments
You can write comments in two different ways using LESS. Regular CSS comments show up in the CSS output produced by the LESS compiler:
/* This comment will appear in the compiled CSS */
You can also use //
to create single-line LESS comments. These are removed by the LESS compiler:
// This comment will not appear in the compiled CSS
Importing other LESS and CSS files
If your LESS stylesheet grows very large then you might want to split it into several .less
files. You can then import the individual .less
files into a main stylesheet using the @import
directive:
@import "common.less";
@import "forums.less";
If you want to import a regular CSS file without running it through the LESS compiler, just make sure your file has a .css
extension:
@import "standard.css"; // This file won't be parsed by LESS
Escaping stuff with the e()
function
The e()
function lets you escape a value so that it’s passed straight through to the compiled CSS, without being parsed by the LESS compiler. This can be handy when working with non-standard CSS that LESS doesn’t understand:
body {
filter: e("progid:DXImageTransform.Microsoft.gradient(startColorstr='#aaaaaa', endColorstr='#666666')");
}
This will produce:
body {
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#aaaaaa', endColorstr='#666666');
}
Pre-compiling LESS code into CSS
The one obvious drawback with LESS is that it requires JavaScript to be enabled in the user’s browser. If JavaScript is turned off — or the browser can’t run JavaScript — then the resulting page will look pretty messy!
Even for browsers that do run JavaScript, there’s a slight overhead associated with downloading and running the less.js
file.
Because of these issues, you may want to use less.js
purely for developing your site. When putting the site live, you can pre-compile your LESS code into a regular CSS stylesheet, which you then serve on your live site instead of the LESS code.
Here are some ways to pre-compile LESS into CSS:
- Run
less.js
using Node.js
You can run theless.js
script outside the browser by using the Node.js JavaScript framework. See the relevant section in the LESS documentation for instructions. - Use lessphp
lessphp is an implementation of the LESS compiler written in PHP. You can run it manually to create a CSS file as needed, or you can set it up on your server to compile as required whenever a page is requested (see the documentation for details).lessphp’s syntax has a few differences from regular LESS, including abstract blocks, a semicolon instead of a comma as the mixin argument separator, and (at the time of writing) no support for the colour functions.
- Use an online compiler
If you just want to compile some LESS code quickly without installing a compiler, you can use an online compiler. The lessphp site has an online version you can use. There’s also OnLess. - Less.app (for Mac users)
If you’re a Mac user, a great free tool is Less.app. This application automatically watches your LESS stylesheets and, whenever you change them, it auto-compiles them into CSS files ready for your website to use. Nice!
Summary
In this tutorial you’ve explored LESS, a dynamic stylesheet language that can make your CSS coding easier. You looked at:
- What LESS is, and why it’s worth using
- How to install and use LESS
- Using variables to define a value once, then reuse it throughout your stylesheet
- Reusing whole rulesets with mixins
- Nesting rules to make concise, easier-to-read code
- How to use operators and functions to calculate values within your stylesheet
- CSS vs. LESS comments
- Importing LESS and CSS files into a LESS stylesheet
- Escaping values with the
e()
function, and - How to pre-compile LESS into CSS so that it can be read by all browsers.
Need more info on using LESS? Check out the official LESS website for the full spec.
Enjoy!
cat says
Wow, there’s some really useful stuff in there. I particularly like variables and arithmetic. Personally I wouldn’t want to put out a live site that relies on LESS, so I love the idea of generating the CSS for the live site. I’m going to give it a go for my next project… will let you know how I go.
(Love the new syntax highlighting on elated too!)
matt says
Thanks cat! Yeah I think the syntax highlighting makes the code much easier to read. I now just need to go back through all our older articles and add it in… 😉
Crazyhunk says
I really like the concept of LESS, but 1 thing that puts e off is that, I am used to the traditional style of css coding and getting used to this can take some time… that said… once I get used to it, working on a different environment can be difficult… I think I would stick to traditional coding for now… even though it make take more time ..
cheers
matt says
@Crazyhunk: Yes, I understand where you’re coming from. What I like about LESS though (compared to other similar languages like Sass) is that it’s very close to native CSS, which makes it pretty easy to pick up and use.
physicsmazz says
Great article, you pointed out some stuff I never new about.
I’ve tried using LESS in the past, but for some reason I had issues with Chrome not updating the styles correctly…anyone else had this issue.
The other thing that turned me off was that I use firebug a lot…and having those line numbers saves me a bunch of time.
matt says
@physicsmazz: Thanks for your comment! I haven’t seen any problems with LESS and Chrome – maybe they’ve fixed it now.
Cheers,
Matt
Jighead says
Hi,
I am unable to get less.js working. Is there anything I need to install on the server? I have tested with your online examples as above. I have the style.less before the less.js as described above etc. My Pathing is all correct. Yet less.js does not seem to compile on the fly as it should. I’ve also added .less mimetype to IIS7 as text/css and it still does not work. I’ve tested this both at my work PC and home PC and both respond the same way.
I’ve googled this issue and a number of others users have the same issue but noe of the answers given seem to work.
I know I can compile using online compilers but that makes using less in development a pain. Any help from anyone would be greatly appreciated.
Thanks
matt says
@Jighead: Strange. Do you see any JS errors in your browser console?