Friday, 23 August 2013

My first introduction to less.js with Bootstrap

What is Less?

Less, which you can find at lesscss.org is a great idea and very simple to understand. Imagine you are writing CSS and you want two things to be the same colour, normally you would do something like the following:

body { color: #f00; } a:link { color: #f00; }
So imagine if you want to change this colour? You would have to find and replace it: but that is not so bad. Imagine, however that you are trying to create a gradient from your colour:

.btn { background-image: linear-gradient(to bottom, #ff0000, #dd0000); }
The problem here is that if you change the red colour, you probably also need to change the other end of the gradient, this would be a different value to find/replace. Add in things like hover colours, visited links etc and the whole thing can be really hard. I was using Twitter Bootstrap (getbootstrap.com) and tried to make the button colours different from what I had downloaded. The buttons ended up looking terrible because I didn't know which colours to change and how.

Enter less (or rather "less css"). There are two really cool things you can do (and plenty of others you can find out about yourself). You can define variables which can be shared across definitions and you can define functions which can be applied to numbers/variables/colours etc (well, there are functions built-in, I assume you could add others if you really needed). So, example 1 above might be:
@textColour: #F00;
body { color: @textColour; } a:link { color: @textColour }
As you might imagine, when you process the less files, the variables are replaced by the values but it is more useful than that. You could also have things like:
@textSize: 18px;
h1 { font-size: @textSize * 2; }
h2{ font-size: @textSize * 1.8}
(note the fact that the variable has the "px" on the end but can still be multiplied) but you could also have:
@textSize: 18px;
@someMultiplier: 2;
h1 { font-size: @textSize * @someMultiplier; }
h2{ font-size: @textSize * 1.8}
That's cool. There is one other thing that is worth mentioning and that is functions, these allow you to do things to numbers or variables that, again, allow a top-level variable to be manipulated throughout your css. Here are some examples:
.btn { background-image: linear-gradient(to bottom, @textColour, darken(@textColour, 20%); }
 .btn { width: round(@buttonWidth / 3, 2); }
.special-window { height: cos(@windowWidth ; }

Downloading and compiling less

So, let us take Bootstrap for example. This uses less to compile the css so if we download the source for bootstrap and look in the less directory, you will notice there are about 30 .less files and each of these looks like css but with the additional functions and variables - they are obviously invalid as css until they have been processed. In the case of Bootstrap, the most important files are bootstrap.less which is the top level file and which is the only one that should be compiled and variables.less which contains all of the user-defined variables that are supposed to be modified.

 You will need a less compiler, I used WinLess, which is free. Start by downloading this and add the folder which contains all the less files from bootstrap and they will all be listed on the right-hand side. You might get errors since all the files will be ticked to compile by default but since bootstrap.less includes the other files, most of them will fail compilation. Don't make any changes initially, just un-tick all of the "compile" checkboxes on the right-hand list in WinLess except for bootstrap. Initially, untick the option to minify it and press compile. All things being equal, you should end up with bootstrap.css in the same directory as your less files and it takes less than a second to compile. You should do this before any changes just to make sure that the build process is working.

Once you have the compiler working, you can start to get to work. There are two things you might want to do. Firstly, by editing bootstrap.less, you can remove any modules that you are not using. For instance, navbar.less is quite big so if you are not using the navbar, you can comment out the include in bootstrap.less. As soon as you save any changes into this directory, WinLess will automatically rebuild the css file. After any changes, you may or may not want to include the file into a project just to check you haven't broken anything.

The second thing you will want to do is change the variables in the file variables.less. These are the only variables in Bootstrap that you are supposed to change (but you can change others, see later on) and again, once you save it, WinLess will automatically rebuild bootstrap.css.

More Customisations

Let's face it, there will be things that are hard-coded in bootstrap and other less files that are not derived from the variables and which won't be how you want them. You could override them in your own CSS but part of the fun of less is being able to specify these before generating the CSS so you don't have to override them. No doubt some people would argue this is bad for maintainability but Bootstrap 3.0 is already completely different than 2.3 so this won't be a problem for me!

For example, Bootstrap defines a modal dialog and the footer, where the buttons live, has a class called modal-footer. By default, this has a hard-coded background colour of some weird grey/biege, which is not what I want for my dialogs. I have two options, I need to modify modals.less (in this case) and change the css entry to either a different hard-coded value (and rebuild) or otherwise to define either a variable to put into variables.less which allows it to be customised or if I think it can be derived from an existing variable, such as body background colour, then I could use that variable instead. I could obviously alter any other variables such as darken the background colour by X percent or whatever. In my case, I also removed the border between the header, body and footer in the modal dialog so it looked like my design.

Obviously, you need to be more careful with hard-coded sizes. You might change a font size and it then conflicts with a different line-height or whatever but you can often tell by testing. I would also warn not to make too heavy changes to your less files otherwise they will become pretty tricky to maintain in their own right.

Using the files in your project

The easiest way to do this, like I described above, is to have WinLess running stand-alone and to copy the bootstrap.css into your project. Once you are ready to deploy, you can minify it also (and test it again!). There are, however options in different web scripting languages to generate css from less files dynamically by uploading all the less files to the web server and have some javascript compile these and store the results in cache. This was hard for me to do in .Net, especially since I already use a bundling tool for my scripts and css files. Also, I don't see a great advantage in this as opposed to just uploading the final css file itself but by all means check it out if you are interested in that.

Post a Comment