Peter Keating

Developer from the New Forest in the South of England.

Setting up my LESS Environment for CSS


Whenever I get my hands dirty with CSS, I always use LESS to assist. If you're not familiar with LESS then their own description summarizes it well.

LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions. LESS runs on both the client-side (Chrome, Safari, Firefox) and server-side, with Node.js and Rhino

In this blog post I am going to go through how I develop CSS with LESS and go into details on a workflow that has worked well for me.

Getting LESS up and running

As the description says, LESS runs on the client & the server. As I'm not familiar with Node.js or Rhino I haven't tried running LESS server side. The client side version of LESS works by including a JavaScript file, and importing LESS files (with the .less extension) similar to how the usual CSS import works, however the type changes to stylesheet/less. A basic example of a HTML page that uses client side LESS is shown below.

<html>
<head>
    <title>LESS client side example.</title>

    <link rel="stylesheet/less" href="css/less/styles.less" />

    <script src="/js/vendor/less-1.3.0.min.js"></script>
</head>

<body>
</body>

</html>

The less-1.3.0.min.js can be download from the official LESS website. When loading the page, if you check the JavaScript console you can see some useful output messages on the LESS conversion to CSS. If your styles aren't displaying as expected, then check the console as the error will be displayed there.

Once your up and running with LESS it is worth checking out their website to see the extra capabilities you now have when writing CSS.

Deployment

There are a couple of disadvantages to running LESS on the client side. Firstly there is a dependency on the client having JavaScript, and having it enabled. If JavaScript isn't enabled then a fallback would need to be provided otherwise your website won't have any CSS. The second problem, which is a minor one because LESS on the client is quick, but time on page load is spent converting the LESS to CSS. With mobile browsing growing at a huge rate, it is important that the page load time is as a low as possible.

In order to make the product version of a website as quick as possible, I use a build script in order to convert LESS to CSS before deployment. That way when the page load occurs, there is no reliance on JavaScript & it will now use a traditional CSS process meaning no time is spent converting. It should be noted, that I only use this for deployment, not during development. For development I stick with using client side LESS, this is to reduce development time spent waiting for build scripts to run. Being able to change styles, refresh and instantly see changes like when developing with traditional CSS is a huge plus.

The Build Script

In order to convert from client side LESS used during development, to a traditional CSS used for the production version I use a build script. The build script is written for use by my favored build tool, Ant. The build script will convert specified LESS files into CSS, convert the LESS file imports in the HTML to point at the new CSS one and finally remove the LESS JavaScript library import.

Lets start with converting the LESS files into CSS files. In order to do this on my Windows machine, I use a LESS compiler created by Duncan Smart that is hosted on Github. The compiler can convert LESS files to CSS via the command line, which is a perfect fit for Ant. The target for converting LESS to CSS is shown below.

<property name="included.less.stylesheets" value="first.less,second.less"/>
<property name="tool.lessc" value="/build/tools/lessc/lessc.cmd"/>
<property name="css.dir" value="css" />
<property name="less.dir" value="less" />

<target name="-less">
     <for param="less.file" list="${included.less.stylesheets}">
        <sequential>
            <echo>compiling @{less.file} to @{less.file}.css</echo>
            <exec dir="${basedir}" executable="${tool.lessc}" failifexecutionfails='true'>
                <arg line='"${basedir}/${css.dir}/${less.dir}/@{less.file}" "${basedir}/${css.dir}/@{less.file}.css"' />
            </exec>
        </sequential>
    </for>
</target>

It should be noted, in order to use the for tag the Ant-Contrib library needs to be included, which provides extra functions for the build script. The target above will loop through a comma separated list of LESS files that should be compiled into CSS. Each LESS file is passed to Duncan Smarts LESS command line tool, with the output file being placed into the CSS directory having the same name as the original LESS file with a .css extension. So, if the value of "${included.less.stylesheets}" is "first.less, second.less", the output would be two files in the CSS directory, "first.less.css" & "second.less.css". If a problem occurs during conversion then the build will fail and details about the error will be displayed. Something to consider if you use source control, is that personally I don't include any .less.css files in the source control because they shouldn't really be touched, only ever created via the build script.

The next step is to swap the LESS stylesheet imports for the converted CSS files. Before doing this, all the source files that will be used in the production release are copied to a temporary directory (intermediate directory). This prevents the build script modifying any of the original source files that are actively developed on. This provides a level of protection in case something goes wrong with the build process, you can feel safe in the fact the source files aren't affected. The target below shows the modification of the LESS style imports used during development, for the traditional CSS imports for the production.

<property name="included.less.stylesheets" value="first.less,second.less" />
<property name="pages-files" value="header.php" />
<property name="intermediate.dir" value="${basedir}/deploy/intermediate" /> 

<!--
     Modifies any .less external stylesheet imports, and converts them 
     to be directed at the compiled .css versions of the .less files.
 -->
 <target name="-lesstocss">
     <for param="less.file" parallel="true" list="${included.less.stylesheets}">
          <sequential>
               <replaceregexp  match="&lt;link(.+)href=['&quot;]?(.*)/less/@{less.file}(?:\?.*)?['&quot;\s]?(.*/?&gt;)"
                               replace="&lt;link rel=&quot;stylesheet&quot; href=&quot;\2/@{less.file}.css&quot;\3" flags="m">
                   <fileset dir="${intermediate.dir}" includes="${page-files}"/>
               </replaceregexp>
          </sequential>
     </for>
 </target>

Like the previous target that converts the LESS files to CSS, the target above loops through a comma separated list of LESS files modifying a list of specified HTML pages converting the LESS style declarations for the converted CSS ones. Typically the list of HTML files (specified in the ${page-files} property) will only include a single file. If your including more than a single file then you should look at the structure of your website, as your probably repeating code. For my WordPress theme, all the style declarations are specified in header.php, this is then reused in every page. So the target above will change any LESS stylesheet imports to the converted CSS stylesheets in header.php.

The final target for the LESS to CSS conversion is removing the redundant LESS JavaScript library that is included in the websites head section. The target below will loop through the same list of HTML files that was used in the previous task, stripping out the script tag that loads the LESS client side library. A regular expression is used matching the specific script tag replacing it with nothing.

<property name="js.libs.dir" value="${basedir}/js/vendor" />
<property name="pages-files" value="header.php" />
<property name="intermediate.dir" value="${basedir}/deploy/intermediate" /> 

<!--
    Removes the client side less javascript library.
-->
<target name="-removeclientless">
    <replaceregexp  match="&lt;script src=&quot;.*${js.libs.dir}/less-1.3.0.min.js&quot;.*&gt;" replace=" " flags="m">
        <fileset dir="${intermediate.dir}" includes="${page-files}"/>
    </replaceregexp>
</target>

After all the LESS conversion via the build script the resulting HTML page based on the initial example at the top of the post should look something like the one below.

As you can see, there is no longer any dependency on JavaScript, and traditional CSS is being used to import the websites styles. Typically in the build scripts I have written, there will be multiple LESS and CSS files, so the build script would go through and concatenate and compress them, however I think that is perhaps a blog post for the future.

Some extra goodies via lesselements

When using LESS, one of the first things I do is grab a useful library of mixins for common patterns of CSS, such as specifying rounded corners, gradients and drop shadows. This library is known as lesselements and is open source on Github. Unfortunately the original creator doesn't maintain the library with no changes in 10 months and 10 pull requests sitting there. Luckily this is Github, and there are plenty of more up to date forks available. My preferred one can be found here, and is more up to date with the latest vendor prefixes and enough documentation to get you started. Also it is actively maintained, I submitted a pull request for a minor tweak to their documentation, and it was accepted by the time I woke up the next day. There are many more forks to choose from, or you could even fork the original library yourself.

Summary

I love LESS. It has brought a lot of needed features to CSS and I think I have found a workflow that works well. Using client side LESS for development allows for quicker development enabling me to see changes to the styles instantly. Having a build script that can handle all the conversion with minimal maintenance is perfect too, there is n need to worry about anything and I know my production version will be quick and snappy without a dependency on the client having JavaScript. If you would like to see an example of what an entire build script for a project looks like then I would take a look at the build script for DotnetMvcBoilerplate.

I have created an example for download of everything discussed in this post that you could use as a great starting point or just to play around with to see what I am talking about.

Any questions once again, feel free to email me or tweet me.

Back to Posts

-->