Overview
dotLess is a .NET port of the less CSS framework. It’s essentially a CSS-like syntax for creating stylesheets supporting inheritance, variables, mixins and simple arithmetic.
Web browsers obviously don’t understand dotLess syntax, so before a dotLess stylesheet is sent to a browser it needs to be parsed into “standard CSS”.
This post walks you through setting up dotLess CSS for a new ASP.NET project. It’s not an in-depth tutorial on dotLess CSS syntax.
Development versus production workflow
In development, we use a handler for parsing dotLess stylesheets on the fly. This allows us to make modifications to the dotLess CSS and then simply reload a page in the web browser to see the results.
In production we exclude the handler and instead use a pre-parsed minified version of the stylesheet. This pre-parsed minified version is updated each time the website project is built.
Download dotLess binaries
The dotLess project is hosted on github, you can download the dotLess binaries here.
Add the dotLess assembly to the project
First, include the dotLess assembly somewhere in your project. I usually keep third-party assemblies in a specific folder in order to properly include them in source control:
Next, reference the dotLess assembly (not necessarily required, but it allows validation when adding dotLess handlers):
Include dotLess compiler
Add the dotless.Compiler.exe executable (used to parse and minify dotLess stylesheets) to your project. I choose to keep it together with the MSBuild configuration file(s) as we use it as part of the build script:
Set up dotLess build script for parsing and minifying
When we build the website, we use dotLess to compile and minify the dotLess-formatted stylesheets. We do this by parsing the dotLess stylesheets into a minified version consisting of “real” CSS, with “.min.” added to the filename. Ie, main.css (dotLess syntax) becomes main.min.css (real minified CSS).
The build script for triggering the dotLess parsing is included in the MSBuildStylesheets.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/MsBuild/2003">
<Target Name="CompileDotlessCss">
<ItemGroup>
<Binaries Include="*.dll;*.exe"/>
</ItemGroup>
<!-- Compile dotLess CSS into minified full CSS -->
<Exec Command="$(ProjectDir)..\[MSBuild]\dotless.Compiler.exe $(ProjectDir)..\css\main.css $(ProjectDir)..\css\main.min.css -m"/>
</Target>
</Project>
Add dotLess handlers
We use two separate handlers for serving stylesheets. In development we use the dotLess handler to parse dotLess stylesheets and serve them as standard non-minified CSS.
In production we use a static file handler to serve pre-parsed minified stylesheets created as part of the build script we set up earlier.
<system.webServer>
<handlers>
<!-- For production -->
<add name="stylesheetsProduction" verb="GET,HEAD" path="*.min.css" type="System.Web.StaticFileHandler, System.Web" />
<!-- For development -->
<add name="stylesheetsDevelopment" verb="GET,HEAD" path="*.css" type="dotless.Core.LessCssHttpHandler, dotless.Core" />
</handlers>
</system.webServer>
Add dotLess configuration element to web.config
dotLess comes with its own configuration element type. We add the dotLess configuration section to web.config like so:
<configSections>
<section name="dotless" type="dotless.Core.configuration.DotlessConfigurationSectionHandler" />
</configSections>
Since we only use the dotLess handler for development we want to disable minification and caching (remember that we use a pre-parsed and minified version for the production environment):
<dotless minifyCss="false" cache="false" />
Quick-start dotLess tutorial
Here are some really brief examples of dotLess CSS syntax for using variables, mixins, inheritance and arithmetic.
You can use variables like this:
/* Define variable */
@standard-margin: 30px;
body
{
/* Use variable */
margin: @standard-margin;
}
Mixins are basically variables, but for entire CSS classes as opposed to individual attribute values:
/* Define mixin variable */
.warning-text
{
color: Red;
font-weight: bold;
text-decoration: blink;
}
/* Use mixin variable */
p.warning
{
.warning-text;
}
a.alert
{
.warning-text;
}
You can use style inheritance like so:
p
{
/* Paragraph style */
border: solid 1px #999;
/* Links inside paragraphs */
a
{
font-weight: bold;
}
/* Span tags inside paragraphs */
span
{
font-size: 16px;
/* Links inside span tags inside paragraphs... */
a
{
text-decoration: underline;
}
}
}
You can use simple arithmetic for calculated values inside your stylesheets:
div.floaters /* Pun intended */
{
float: left;
/* We have two of these div elements
We want each to take up half of the content width
but we want to leave room for margin between them */
width: @content-width / 2 - @margin / 2;
}
div.floaters.first
{
margin-right: @margin;
}
Linking the correct stylesheet
We want to use the standard non-minified stylesheet when we’re developing. Like we’ve set up the handlers we’ll use the dotLess handler in development, but the pre-parsed stylesheet in production.
This can be done in multiple ways, but here’s a code sample adding a stylesheet link programmatically depending on the debug setting for the website:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// Add stylesheet link
var stylesheet = HttpContext.Current.IsDebuggingEnabled ? "main.css" : "main.min.css";
var stylesheetLink = new HtmlLink { Href = string.Concat("/css/", stylesheet) };
stylesheetLink.Attributes.Add("rel", "stylesheet");
stylesheetLink.Attributes.Add("type", "text/css");
Header.Controls.Add(stylesheetLink);
}
So, when our web.config looks like this…
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
…we get this in our markup:
<head>
<title>dotLess</title>
<link href="/css/main.css" rel="stylesheet" type="text/css" />
</head>
And when we switch of debugging, as in our production environment…
<system.web>
<compilation debug="false" targetFramework="4.0" />
</system.web>
…we get the minified stylesheet linked instead (notice the “.min.” part of the stylesheet filename):
<head>
<title>dotLess</title>
<link href="/css/main.min.css" rel="stylesheet" type="text/css" />
</head>