Style Tools

Less to CSS Compiler

Compile Less stylesheets to CSS directly in the browser. Supports variables, mixins, nesting, and all core Less features.

Loading Less compiler...
Less Input
Compiled CSS

What is a Less to CSS compiler?

Less is a CSS preprocessor, a superset of CSS that adds variables, mixins, nesting, guards, and colour and maths functions. Browsers understand none of it. So Less has to be compiled down to plain CSS before it can be served, and a Less to CSS compiler is what performs that step: it reads a .less stylesheet, resolves the variables and expands the mixins, flattens the nesting into full selectors, evaluates the arithmetic, and prints ordinary CSS on the other side.

This page runs Less.js 4.2.0 in your browser, the reference compiler, the same one lessc uses. Paste Less into the left panel and the compiled CSS is waiting opposite before you have finished typing. No convert button, no build tooling to install. Variables, parametric mixins, guards, detached rulesets, parent references, and the colour functions all behave exactly as they would in a real build, because it is the real compiler. If something does not compile you get Less's own error message in place of half-finished output, and Copy CSS puts the result on your clipboard.

When to use it

Inherited code is what brings most people here. Bootstrap 3 was written in Less, and a decade later there are still thousands of live sites carrying a variables.less full of @brand-primary and @grid-gutter-width. Somebody needs to know what a rule resolves to before touching it, and standing up a Node toolchain to answer one question about one selector is out of proportion to the question. Paste the block in, read the CSS, make the change.

The same thing happens with themes whose build has gone missing. A WordPress or Drupal theme ships with a less/ directory, the Gruntfile references plugin versions that no longer install, and the person who set it up left three years ago. You do not need the pipeline back. You need this one file compiled, so you can patch the compiled CSS directly or start moving the theme off Less entirely. Compiling in a browser tab sidesteps the whole dependency problem, because there are no dependencies.

Then there are the small, frequent checks. What does a nested mixin call expand to, when the source is four levels deep and calls two other mixins on the way down? Is darken(@brand, 10%) the colour you think it is? And there is the steady trickle of snippets out of 2014 blog posts and Stack Overflow answers (written in Less because everything was, back then) that have to come out as plain CSS before they can go into a project that has never heard of a preprocessor. Paste-and-read jobs, all of them, which is the shape this tool fits.

How this tool works

The compiler itself arrives as a script the page pulls in on first visit, then sits in your browser cache. The toolbar tells you where it is: "Loading Less compiler..." while the script is on its way, then "Less.js ready" with a tick once it can be used. Paste something in that gap and you will see "Less compiler is still loading..." in place of output. The next keystroke compiles it. From there everything runs locally, and your Less is parsed into a real syntax tree, evaluated, and printed, which is why scope, operator precedence, mixin guards, and the colour functions come out exact rather than approximated.

The one limit that catches people out is @import. In a build, an import reads another file off disk. A browser tab has no disk, so Less.js falls back to requesting that file over HTTP, relative to the page you are on, and nothing here serves it. The output panel switches to a compile error naming the URL it tried and the 404 it got back, and the compile stops there. So everything goes in the one box. Inline your dependencies in dependency order: variable declarations first, then mixin definitions, then the rules that use them. Or take the file a block at a time, with just the variables that block references. Two forms survive, neither of them meant to be read at compile time. An explicit CSS import, @import (css) "theme.css", and a URL import, @import url("https://..."), pass straight through as ordinary CSS imports for the browser to resolve when the stylesheet loads.

The compiler runs with compression off, so output is Less's standard formatted CSS: two-space indentation, one declaration per line, one rule per block. That suits a tool you read the answer out of rather than ship from. For production CSS, run it through the CSS Minifier afterwards: compile first, minify second, since that tool expects real CSS and knows nothing about Less. Errors are Less's own too. A missing variable reports "variable @missing is undefined", an unbalanced brace reports the input as unrecognised, and either way a red Compile Error state replaces the output, carrying the message verbatim. Valid CSS is also valid Less, so plain CSS pasted here compiles and comes back reformatted.

Nothing you paste leaves the tab. The only network request this page makes is for the compiler bundle itself. Your stylesheet stays where you put it, and there is no server behind this page that could receive it. For a preprocessor that matters more than it might sound, since a variables file is often the closest thing a client project has to a written record of its unreleased brand palette.

Examples

  • A button built from variables and a mixin

    Input
    @brand: #5fc2ef;
    @radius: 6px;
    
    .button-variant(@bg) {
      background: @bg;
      border: 1px solid darken(@bg, 10%);
      &:hover { background: darken(@bg, 8%); }
    }
    
    .btn-primary {
      .button-variant(@brand);
      border-radius: @radius;
    }
    Output
    .btn-primary {
      background: #5fc2ef;
      border: 1px solid #31b0ea;
      border-radius: 6px;
    }
    .btn-primary:hover {
      background: #3ab4eb;
    }

    This is the Bootstrap 3 pattern in miniature. A mixin definition produces no CSS of its own (it exists only to be called), so .button-variant never appears in the output. Both darken() calls are evaluated at compile time: Less converts #5fc2ef to HSL, subtracts 10 and 8 percentage points of lightness, and converts back. That is where #31b0ea and #3ab4eb come from. The hover rule nested inside the mixin is emitted after the block that called it, as its own top-level selector.

  • Nesting and parent references

    Input
    .nav {
      display: flex;
      > li { margin-right: 1rem; }
      a {
        color: #333;
        &:hover { color: #000; }
        &.is-active { font-weight: 600; }
      }
      &--compact a { font-size: 0.875rem; }
    }
    Output
    .nav {
      display: flex;
    }
    .nav > li {
      margin-right: 1rem;
    }
    .nav a {
      color: #333;
    }
    .nav a:hover {
      color: #000;
    }
    .nav a.is-active {
      font-weight: 600;
    }
    .nav--compact a {
      font-size: 0.875rem;
    }

    One nested block becomes six flat rules. The difference between the two ways of nesting is the thing to read here. A bare selector is joined to its parent with a space, or with whatever combinator you wrote, so a becomes .nav a. An ampersand is replaced by the parent text with no space at all. That is why the nested hover gives .nav a:hover and the nested --compact gives .nav--compact, the trick that makes BEM naming workable in Less.

  • Arithmetic, colour functions, and calc

    Input
    @base: 8px;
    @brand: #2f6fed;
    
    .stack {
      padding: @base * 2;
      gap: @base;
      color: lighten(@brand, 20%);
      border-bottom: 1px solid fade(@brand, 30%);
      width: calc(100% - @base);
    }
    Output
    .stack {
      padding: 16px;
      gap: 8px;
      color: #8db0f5;
      border-bottom: 1px solid rgba(47, 111, 237, 0.3);
      width: calc(100% - 8px);
    }

    Every value here is resolved before it reaches the browser. @base * 2 folds to 16px, with the unit carried through the multiplication. lighten() returns a literal hex. fade() sets the alpha channel and switches the output to rgba(), because hex cannot carry an alpha value. calc() is the exception worth knowing: Less deliberately does no maths inside it, so 100% - @base is left as an expression for the browser to evaluate at layout time, with only the variable substituted.

  • A breakpoint mixin using a detached ruleset

    Input
    @tablet: 768px;
    
    .respond-above(@width; @rules) {
      @media (min-width: @width) { @rules(); }
    }
    
    .grid {
      grid-template-columns: 1fr;
      .respond-above(@tablet; {
        grid-template-columns: repeat(3, 1fr);
      });
    }
    Output
    .grid {
      grid-template-columns: 1fr;
    }
    @media (min-width: 768px) {
      .grid {
        grid-template-columns: repeat(3, 1fr);
      }
    }

    A whole block of rules is passed to a mixin as an argument, then called back with @rules(). Two things happen on compile. The @media query lands at the top level instead of staying nested inside .grid, because CSS does not allow at-rules inside a style rule; the compiler then rebuilds the .grid selector inside it so the declarations still target the right element. Note the semicolons separating the mixin arguments. A comma there would be read as part of the ruleset.

Frequently asked questions

  • How do I convert Less to CSS online?

    Paste your Less into the left panel and the compiled CSS appears on the right as you type. No build step, no npm install, no account. Wait for the toolbar to read "Less.js ready" before pasting, then use Copy CSS to take the result. Everything has to be in that one box, since an @import cannot resolve from a browser tab.

  • Why does @import not work in a browser Less compiler?

    Because Less.js resolves the import by requesting that file over HTTP, relative to the page you are on, and gets a 404 back. In a build the import would read the neighbouring file off disk; here there is nothing at that URL to read. The compile error names the URL it tried, so you can see exactly what failed. Inline the dependency instead: paste the imported file's contents above the code that uses it, in dependency order, or compile one block at a time along with the variables it references.

  • What is the difference between Less and Sass?

    Two preprocessors that solve the same problem, with different syntax and different histories. Less uses @ for variables and a selector-shaped syntax for mixins. Sass/SCSS uses $ for variables, @mixin and @include, and adds control directives such as @if and @each, which Less handles through guards instead. Sass became the larger ecosystem after Bootstrap 4 moved to it in 2018, which is roughly when most new Less projects stopped starting. This tool compiles Less only. SCSS pasted in here will not compile.

  • Can I compile a Bootstrap 3 theme with this?

    One file at a time, yes, provided you bring its dependencies with it. Bootstrap 3's Less is a set of partials that all import variables.less and mixins.less, and those imports cannot resolve here, so paste the variables and the mixins you need above the partial you want compiled. For the whole framework at once you want lessc locally. For reading what one component resolves to, this is faster than getting a decade-old Grunt build running again.

  • Is the compiled CSS minified?

    No. Compression is off, so the output keeps two-space indentation and one declaration per line, which is what you want when the reason you are here is to read it. If the CSS is heading for production, take the output and run it through the CSS Minifier on this site. Compile first, minify second: the minifier expects plain CSS and has no idea what a mixin or a variable is.

  • Can someone help us get off Less entirely?

    Yes. That is a normal engagement for Zinc Online Solutions. A directory of .less files with no working build usually resolves one of two ways: compile it once and move to plain CSS with custom properties, or port it to Sass alongside whatever the rest of the stack already uses. Occasionally neither fits, and the answer is to rebuild the pipeline so the Less source stays authoritative. Which one applies depends on how much of the theme is still being edited. Point us at the repository and we will tell you which it is and what it costs.