Using LESS CSS with ASP.NET

As a software developer, using CSS can sometimes be frustrating as it violates the DRY principles, with a typical CSS file containing a lot of duplication. Fortunately there are a suite of frameworks that can help; CSS extension languages that compile down to standard CSS. LESS CSS is one such framework. A LESS CSS file looks quite similar to a normal CSS file, except that it adds some additional features to the CSS language, which gets complied into standard CSS that your browser will understand. LESS CSS introduces four main features; variables, mixins, nested rules and operations. Let's have a quick look at each.

Variables

Variables allow you to define values in a single place, and re-use them elsewhere. You can use variables for any style value, whether it be a RGB colour code or a font-family declaration. Let's look at an example:

Standard CSS
h1, h2, h3, h4, h5, h6 { color: #f00; }
#rightColumn { border:solid 1px #f00; }
#footer { background-color: #f00; }
LESS CSS
@primaryColour: #f00;
h1, h2, h3, h4, h5, h6 { color: @primaryColour; }
#rightColumn { border:solid 1px @primaryColour; }
#footer { background-color: @primaryColour; }

Mixins

Mixins allow you to re-use several sets of styles as a named unit, so that you can include whole classes into other classes. Even better, a mixin can take parameters so that they act much like a function. Let's look at an example:

Standard CSS
.defaultFeaturedSection {
  border: solid 1px #f00;
  padding: 5px;
  font-size: 1.2em;
}

.blueFeaturedSection {
    border: solid 1px #00f;
    padding: 5px;
    font-size: 1.2em;
    background-color: #00a;
}

.greenFeaturedSection {
    border: solid 1px #0f0;
    padding: 5px;
    font-size: 1.2em;
    background-color: #0a0;
}
LESS CSS
.featuredSection (@colour: #f00) {
  border: solid 1px @colour;
  padding: 5px;
  font-size: 1.2em;
}

.defaultFeaturedSection {
    .featuredSection;
}

.blueFeaturedSection {
    .featuredSection(#00f);
    background-color: #00a;
}

.greenFeaturedSection {
    .featuredSection(#0f0);
    background-color: #0a0;
}

Nested Rules

This feature allows us to nest our styles hierarchically, rather than having to repeat the same selectors over and over again. Look at how much neater our LESS CSS code is compared to standard CSS.

Standard CSS
#wrapper { background-color:#ccc; }
#wrapper h1 { font-size:1.4em; color:#333; }
#wrapper .mainContent { margin:10px; }
#wrapper .mainContent h2 { margin:10px; }
#wrapper .mainContent a { text-decoration: none; }
LESS CSS
#wrapper {
    background-color:#ccc;
    h1 { font-size: 1.4em; color:#333; }
    .mainContent {
        margin:10px; 
        h2 { font-size: 1.3em; }
        a { text-decoration: none; }
    }
}

Operations

This powerful feature lets you define style values with an expression, which means you can set style values based on numerical operations on one of your variables. Rather usefully, you can also apply these operations to colour values, for instance you can define a colour variable that is 50% darker than another colour variable you have declared. An example:

Standard CSS
h1 { color: #f00; }
h2 { color: #800000; }
LESS CSS
@primaryColour: #f00;
@secondaryColour: @primaryColour * 0.5;
h1 { color: @primaryColour; }
h2 { color: @secondaryColour; }

Integrating with ASP.NET

So all of this is great, but how do I actually use this in an ASP.NET app? The official LESS CSS implementation is in Ruby, but there is a .NET port called dotLESS to make it easy to integrate with ASP.NET. You can download the required assemblies/tools from the web-site, but it's probably easier to use NuGet to add the dotLESS package to your project. There are two ways that you integrate LESS CSS files into your app, either you can use an HTTP Handler to compile your LESS CSS files on-the-fly, or you can set-up a post-build action to compile your LESS CSS files prior to deployment. Let's look check out both options:

1) HTTP Handler to compile LESS CSS files on-the-fly
Ensure you have added dotless.Core as a reference, and ensure that your web.config file contains the highlighted lines:

<?xml version="1.0"?>
<configuration>  
    <configSections>
        <section name="dotless" type="dotless.Core.configuration.DotlessConfigurationSectionHandler,dotless.Core" />
    </configSections>

    <dotless minifyCss="true" cache="true" />

    <system.web>
        <httpHandlers>
            <add type="dotless.Core.LessCssHttpHandler,dotless.Core" validate="false" path="*.LESS" verb="*" />      
        </httpHandlers>
    </system.web>
</configuration>

The above configuration will route any http request ending in ".less" coming into your site to run through the dotLESS compiler to be converted into standard CSS. We've also specified that the CSS should be minified and cached for maximum efficiency.

2) Post-build action to compile LESS CSS files before deployment
Given that CSS files rarely change after an app has been deployed, a good solution is to compile your LESS CSS files before deployment. The advantage to using the HTTP Handler method is that you land up with normal static files, which IIS can serve more efficiently than running through a handler, and it also means that you files can be hosted externally, e.g. on a CDN. The simplest way to achieve this is by using a post-build action on your web project. dotLESS ships with a command line tool to compile LESS CSS; if you used NuGet to add dotLESS to your solution, the executable can be found at {solutionPath}\packages\dotless.1.1.0\Tools\dotless.Compiler.exe).

So in Visual Studio, open the properties of your web project, go to the "Build Events" section, and the in the section "Post-build event command line", insert the following line:

$(SolutionDir)\packages\dotless.1.1.0\Tools\dotless.Compiler.exe -m "$(ProjectDir)\content\*.less" "$(ProjectDir)\content\*.css"

Every time the project builds, this command will compile any .less file in the \content folder into a corresponding .css file, minifying it as well (with the -m switch).

During development this post-build approach can be frustrating as any changes you make to your .less files while your app is running are not reflected until you next build the project. Fortunately dotless.Compiler.exe has a -w switch which watches for changes to your .less files, so you can make changes without having to rebuild.

TIP
You don't actually have to use the extension .less, you can use anything. Visual Studio doesn't know how to handle .less files, so it treats them as a standard text file. If you use the naming convention {filename}.less.css, then Visual Studio will treat it as a standard CSS file and provide some formatting and intellisense. Sure it's not perfect as Visual Studio doesn't know how to handle the LESS specific features, but it's still better than nothing.

Comments (7)

Realto
You're probably already aware of this, but I figured I would add this for the benefit of someone else that might read this post:

I followed your advise in the "TIP" and changed the file extension from .less to .less.css and the I altered the web.config like so

<add type="dotless.Core.LessCssHttpHandler,dotless.Core" validate="false" path="*.LESS.CSS" verb="*" />

So now I can reference the ".less.css" file in the html and it works on the site. That was probably what you meant in that TIP, I just wanted to try and make it work completely like that so I could use the css syntax that's already built into VS.

Thanks!
Thursday, 08 December 2011 03:32
lesscss
thanx for ur help....
Tuesday, 26 March 2013 07:33
Nacho
:(
I have VS 2012, I installed with nuget the less (this added the lines in web.config), but the styles not apply.
I can open the .less file in chrome and see the code, but the styles never apply :(
Why!
Thursday, 25 April 2013 17:38
Borito
Hey Nacho,
did you link up the less css to the page?
Wednesday, 21 August 2013 21:34
Hatem
Where should i place the <add....>
in web.config ?
Saturday, 17 May 2014 17:03
G10
Just wanted to make a note here. The command mentioned in the step-2 will not work with MS Visual Studio Ultimate 2013 running in the integrated mode. You will have to put the compiler path in the double quotes as shown below. I have omitted the output css file name because it automatically names it general.css based on general.less

"$(SolutionDir)packages\dotless.1.4.4\tool\dotless.compiler.exe" -m "$(ProjectDir)Content\themes\general\less\general.less"
Tuesday, 31 March 2015 14:22
Abhijeet
I have followed all the steps but still less file is unable to compile

here is my web.config-

<configSections>
<section name="dotless" type="dotless.Core.configuration.DotlessConfigurationSectionHandler, dotless.Core"/>
</configSections>
<dotless minifyCss="true" cache="true" web="false" strictMath="false"/>
<system.webServer>
<handlers>
<add name="dotless" path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler,dotless.Core" resourceType="File" preCondition="integratedMode"/>
</handlers>
</system.webServer>
<!--<add name="less-handler" type="dotless.Core.LessCssHttpHandler,dotless.AspNet" path="*.LESS" verb="*" />-->
<system.web>
<compilation debug="true" targetFramework="4.5"/>
<httpRuntime targetFramework="4.5"/>
<httpHandlers>
<!--<add path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler, dotless.Core"/>-->
<add type="dotless.Core.LessCssHttpHandler,dotless.Core" validate="false" path="*.LESS" verb="*" />

</httpHandlers>
</system.web>


2. Also followed the second step


What is missing.. ??




Monday, 22 June 2015 10:12
Add a Comment