Centric connect.engage.succeed

Do more with LESS

Geschreven door Martijn Kloosterman - 15 februari 2017

Martijn Kloosterman
Everyone wants a pretty website, but no developer wants to be confronted with a pile of confusing, self-overwriting stylesheets. CSS has the tendency to balloon out of control if you don’t keep a tight leash on it, especially when working in teams. To steer clear of a situation where file-loading order has become paramount, or where you dread you’ll get lost in the forest of !importants, you should consider using CSS preprocessors. These handle all managerial tasks and return a simple, optimized file.

So, what exactly is LESS?

LESS is a dynamic stylesheet language. It is a scripting language that lets you generate your CSS at the press of a button, making for a far more dynamic implementation. In other words, it produces stylesheets to make your website pretty. To implement it you need to use a LESS preprocessor, like LessJS. This lets you simplify the tedious task of writing stylesheets manually, which is often a part of developing.

Other preprocessors are available too, covering a range of platforms and languages. You can find a comprehensive list of LESS preprocessors on Wikipedia (1). And LESS is not the only preprocessor language available either: the other big name you can use is SASS/SCSS. There are also a handful of lesser-known ones, but these are quite obscure and support will be minimal.

We’ll start with a simple example to show you what LESS can do for you. At its very basic level, it takes a variable and copies it to where needed, turning the LESS into valid CSS.

So, this

@color: purple;

html {
	background-color: @color;
}

will be processed into this

html {
	background-color: purple;
}

…which is something the browser will understand, responding with a glorious purple background. This may not be a very exciting example but, fortunately, LESS gives you many more toys to play with. You have access to all sorts of built-in features, including custom functions, Boolean logic, looping, inheritance and importing files. The functionality, which is pretty straightforward, is added to all the regular CSS functionality you already have. For a full list of functionality look at the features (2) here.

Since CSS is fully compatible with LESS, as long as you already have CSS in your project (and I hope you do), you can simply rename your CSS files to .less. In that sense, it’s comparable to introducing Typescript into an existing solution: rename your .js to .ts and you’re good to go. Many of the popular web components come with their own styles already in .less format, making it easy for you to integrate it all. Bootstrap, for example, comes with a full set of LESS files, ready for you to implement. You can even tweak the LESS files on the Bootstrap website (3), so you hit the ground running.

What LESS is doing for my project (and could do for yours as well?)

Do more with less

I am currently working on an SaaS implementation project involving a portal with many different tenants, each providing their version of this same software to their own customers. To differentiate between the sites, a tenant can change several style settings through an administration module. These choices are stored in a database.

Since we were already using LESS for the basic styles of the generic user, and using a Gulp task to generate default CSS files for each tenant, I decided to delve deeper and figure out if it was possible to introduce multi-tenancy into dynamic style generation. You don’t want to have to recompile the entire site every time you add a new tenant, or when the tenant picks a different background color.

There are four main ways to get LESS to spit out your required CSS:

  • During development as a build task or on the development machine
  • Server side during request handling (using dotLess)
  • Client side during page rendering (using LessJS)
  • Hybrid of the above

Each method obviously has its advantages and drawbacks.

During development

There are several ways to get LESS processed during development. If you’re using Visual Studio, you can use Web Essentials for processing on the developer machine. If your LESS files are to be processed as a build step, this won’t be enough on its own. You can consider using Gulp or Grunt in the Visual Studio task runner. It’s good practice not to include the generated CSS files in the solution: this prevents old styles from sticking around as read-only files, breaking your builds.

Advantages:

  • Static CSS means it’s the fastest possible way to get styling to your client
  • Ideal for caching, minifying and other optimizing
  • Least likely to clash with your Content Security Policies

Drawback:

  • It’s static. If you want dynamic styles, you’ll probably end up sending styles to the client it doesn’t always need.

Server side (.Net)

If you’re running an IIS server, it’s as simple as NuGetting your way to ‘Install-Package dotless’. It comes with built-in console support and watch functionality, and can process your LESS both automatically and programmatically. And it’s fairly seamless to integrate it into bundle transformations too. You’ll need to decide which method you prefer for returning CSS to the client: store it to disk or serve it through a file-handler. Keep in mind that without caching and/or the correct meta tags, processing your LESS will happen on every call and might generate a noticeable delay. Dotless is not fully compatible with LessJS – check out the list of differences and caveats (4) on the Dotless website.

Server side (NodeJS)

If you’re running a NodeJS server, implementing LessJS is just as easy: simply grab it from NPM (npm install –g less) and integrate it into your processing pipeline, adding caching where desired.

Advantages:

  • Dynamic: can be custom tailored to your client’s needs
  • Server has plenty of processing speed
  • Cacheable to any level desired

Drawback:

  • It’s always a bit slower than serving static stylesheets if no caching is available.

Client side

The most exotic implementation, and the reason I considered writing this article to begin with, is the client side option: leave the style generation up to the browser. Although it has some advantages, for the most part these are overshadowed by the drawbacks. For the project I was working on, I still considered this solution, using just a small LESS file in addition to the largely static CSS served to the client. This allows the user to select colors on the fly and immediately see the effect in their browser. Saving their choice afterwards is a simple API function and results in the static stylesheets getting updated server-side. It provides the desirable rapid UI feedback and ultimately results in static server-hosted CSS, so it is the best of both worlds.

Advantages:

  • The user immediately sees how it affects their site
  • It uses the same LessJS code both server-side and client-side, improving code maintenance
  • It only communicates the selected values back to the server

Drawbacks:

  • It’s client-only (obviously)
  • More traffic to the client (LESS file and the LessJS library need to be downloaded)
  • Site’s stylesheet design needs to be made compatible with on-the-fly client-side style updates

Here’s a simple example of LessJS running client-side. Create a website in your favourite development environment and then add the index.html and styles.less files shown below to see dynamic LESS processing in the client.

@color1: #000;

body {
    color: @color1;
    text-align: center;

    div.component when (iscolor(@color1)) {

        margin: .5em;
        display: block;

        div {
            height: 1em;
        }

        &.r {
            div {
                width: red(@color1) / 255 * 100%;
                background-color: red;
            }
            border: solid 1px red;
        }

        &.g {
            div {
                width: green(@color1) / 255 * 100%;
                background-color: green;
            }
            border: solid 1px green;
        }

        &.b {
            div {
                width: blue(@color1) / 255 * 100%;
                background-color: blue;
            }
            border: solid 1px blue;
        }
    }

    div.component when not (iscolor(@color1)) {
        display: none;
    }
}

styles.less

<html>
<head>
    <link rel="stylesheet/less" type="text/css" href="styles.less" />
    <script>
        less = {
            env: "development",
        };
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js"></script>
    <script>
        function modifyLess() {
            less.modifyVars({
                'color1': document.getElementById('color-input').value
            });
        }
    </script>
</head>
<body>
    <h1>LessJS Clientside example</h1>
    <div id="content">
        <input type="text" id="color-input">
        <button onclick="modifyLess()">Update LESS variable</button>
        <div class="component r">
            <div></div>
        </div>
        <div class="component g">
            <div></div>
        </div>
        <div class="component b">
            <div></div>
        </div>
    </div>
</body>
</html>

index.html

Once the page is loaded, you can enter any HTML color definition, either by name (red, pink, chartreuse) or hex-code (including the #, like #123456) in the input window to see the browser generate the required CSS dynamically.

The LESS file includes a check to see if the input is a valid color before processing it. This is done using the ‘when’ and the ‘iscolor()’ functionality. It then proceeds to extract the red-green-blue components and displays these as bars. The LessJS script received one optional property on initialization: ‘env’ set to ‘development’ so the resulting CSS isn’t cached in the user’s isolated storage. The other possible value is ‘production’, which does cache. This is not a good idea for an editing environment. See the LessJS website (5) for more options.

Hybrid mode

You could also consider a hybrid solution: a mixture of the previous options, depending on the requirements of your project. You could consider off-loading part of the LESS rendering to the server, mix it with static files generated during the build process or do a few things client side. Just make sure that you validate anything coming from the client so that you don’t end up with dancing pink unicorns on your website.

Less mess is better

To give our tenants the option of picking styles, we settled on a hybrid solution - a small LESS file to instantly override the styles currently used so our tenants can immediately see the effect of the color choice. We did advise them to share it with colleagues before finalizing and inflicting it on their visitors. After all, just because you can pick a color doesn’t mean you should.

Most of the styles are still generated during building though. When tenants choose different colors, the choices are communicated back to the server through a simple web API, and DotLess generates new CSS files for their portal. Simple and straight to the point.

And now what?

Preprocessors aren’t going to go away anytime soon. LESS is a safe bet for the foreseeable future: regardless of your preferred development platform, your investments in LESS will migrate along for now. There is an interesting family feud going on between SASS and LESS (LESS being a descendant of SASS). Depending on who you ask, one or the other is considered the best. Ultimately, it doesn’t really matter: ‘the best’ is simply whichever works for you and your project.

  1. https://en.wikipedia.org/wiki/Less_(stylesheet_language)
  2. http://lesscss.org/features/
  3. http://getbootstrap.com/customize/#less-variables-section
  4. https://github.com/dotless/dotless/wiki/Less-js-differences
  5. http://lesscss.org/usage/#using-less-in-the-browser-options

Martijn Kloosterman is Craft Expert van Team .NET binnen Craft, hét groeiprogramma voor IT'ers (powered by Centric). Wil je zijn blog volgen? Schrijf je in voor de Craft-update.


 

Tags:.NET

     
Reacties
  • Centric
    Arnoud van Bokkem
    22 februari 2017
    Hi Martijn,

    Interesting stuff! Need to read up on the feud, could be entertaining to see what actual arguments are used to defend one or the other family.

    Great to see your expertise added to the Craft community.

    Kind regards,
    Arnoud
  • Centric
    Gert-Jan Verkerk
    27 februari 2017
    Hi Martijn,

    Great article... I already use it with my bootstrap-driven sites. Love to learn more!
Schrijf een reactie
  • Captcha image
  • Verzenden