DevNotes
CSS 18 min read

LESS CSS 2026: Dynamic Stylesheets Complete Guide πŸš€

LESS (Leaner Style Sheets) full reference: Variables (@), mixins, nesting, operations, functions, loops (@for/@each), guards (@if), inheritance, escaping (~"string"), imports, and production patterns vs SCSS/Tailwind.

#LESS CSS #variables #mixins #nesting #CSS preprocessor
Guide CSS

LESS CSS 2026: Complete Preprocessor Guide πŸš€

LESS (Leaner Style Sheets) extends CSS with variables (@), mixins, nesting, math operations, functions, loops, guards (@if), and inheritance. JavaScript-based, CSS-superset syntax, client/server compilation. Simpler than SCSS, perfect for dynamic theming and rapid prototyping.

🎯 LESS vs SCSS vs Tailwind (2026)

FeatureLESSSCSSTailwind v4
SyntaxCSS-likeCSS-likeClasses
CompilationJS/ClientRuby/NodePostCSS
Learning CurveEasyMediumHard
EcosystemSmallHugeMassive
PerformanceFastFastFastest
Modules❌ Basic@useCSS layers

πŸ—οΈ LESS Syntax (CSS Superset)

/* βœ… Valid CSS works in LESS */
.button {
  background: blue;
  padding: 1rem 2rem;
}

/* βœ… LESS Superpowers */
@primary: #3b82f6;
@radius: 0.5rem;

.button {
  background: @primary;
  padding: 1rem 2rem;
  border-radius: @radius;
  
  &:hover {
    background: darken(@primary, 10%);
  }
}

πŸ”₯ 1. VARIABLES (@name)

// Basic variables
@primary: #3b82f6;
@spacing-sm: 0.5rem;
@border-radius: 0.5rem;

/* Design tokens (maps/objects) */
@colors: {
  primary: #3b82f6,
  success: #10b981,
  danger: #ef4444
};

/* Variable interpolation */
@brand: 'MyApp';
.header-@{brand} { color: @primary; }

/* Lazy evaluation */
@size: 30px;
.wrapper { width: @size; height: @size; }

🧩 2. MIXINS (Reusable Blocks)

/* Basic mixin */
.flex-center() {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Mixin with parameters */
.button(@bg: @primary, @size: md) {
  display: inline-flex;
  gap: 0.5rem;
  padding: if(@size = lg, 1.5rem 2.5rem, 1rem 2rem);
  background: @bg;
  color: white;
  border-radius: @radius;
  transition: all 0.2s;
}

// Usage
.primary-btn { .button(); }
.danger-btn { .button(#ef4444, lg); }

πŸ”„ 3. NESTING (DRY Selectors)

.nav {
  background: #111827;
  
  &__item {
    padding: 1rem;
    
    &--active {
      background: rgba(59, 130, 246, 0.1);
    }
    
    &:hover {
      background: rgba(255, 255, 255, 0.05);
    }
  }
}

βž• 4. OPERATIONS & MATH

@base: 16px;
@width: 100px;
@height: @width * 2;
@margin: (@width / 4);

.container {
  width: @width;
  height: @height;
  margin: @margin;
  font-size: (@base * 1.2);
}

/* Color math */
@light-bg: lighten(@primary, 45%);
@dark-text: darken(#111827, 5%);

βš™οΈ 5. FUNCTIONS (Built-in + Custom)

/* Built-in color functions */
.spin(@blade: 0deg, @time: 4s, @repeat: infinite) {
  @-webkit-keyframes spinner {
    to { -webkit-transform: rotate(@blade); }
  }
  -webkit-animation: spinner @time @repeat linear;
}

/* Custom properties */
@my-list: 1px 3px 4px 6px;
@length: length(@my-list);  // 4

.mixin(@index) { 
  margin-left: extract(@my-list, @index); 
}

πŸ” 6. LOOPS (@for / @each equivalent)

/* @for loop (1-12 columns) */
.generate-cols(12);
.generate-cols(@n, @i: 1) when (@i =< @n) {
  .col-@{i} {
    width: (@i * 100% / @n);
  }
  .generate-cols(@n, (@i + 1));
}

βœ… 7. GUARDS (@if / @when)

/* Conditional mixins */
.average(@x, @y) {
  @result: (@x + @y) / 2;
}

.greater(@x) when (@x > 0%) { color: green; }
.greater(@x) when (@x =< 0%) { color: red; }

.triangle-up(@size, @color) when (@size > 5px) {
  width: 0;
  height: 0;
  border-left: (@size / 2) solid transparent;
  border-right: (@size / 2) solid transparent;
  border-bottom: @size solid @color;
}

🎭 8. IMPORTS & PARTIALS

styles/ β”œβ”€β”€ variables.less β”œβ”€β”€ mixins.less β”œβ”€β”€ components/ β”‚ β”œβ”€β”€ _button.less β”‚ └── _card.less └── main.less

// main.less
@import 'variables';
@import 'mixins';
@import (reference) 'components/button';
@import (inline) 'reset.less';

/* Import options */
@import (less) 'file.less';     // LESS file
@import (css) 'file.css';       // CSS file  
@import (reference) 'file';     // Don't output CSS
@import (inline) 'file';        // Output without wrapping

πŸ› οΈ 9. ESCAPING (~β€œstring”)

/* Escape LESS processing */
@variable: 999;
.transition2x: ~"cubic-bezier(0.68, -0.55, 0.265, 1.55)";

.button {
  transition: all 2s @transition2x;
  z-index: ~"@@variable";  // Outputs @999
}

🎨 10. PRODUCTION ARCHITECTURE (7-1 Pattern)

// 1. Settings (Variables)
@primary-color: #3b82f6;
@spacing-unit: 8px;

// 2. Tools (Mixins/Functions)
.flex-center() {
  display: flex;
  justify-content: center;
  align-items: center;
}

// 3. Generic (Reset)
* { box-sizing: border-box; }

// 4. Elements (Base)
body {
  font-family: -apple-system, sans-serif;
  line-height: 1.6;
}

// 5. Objects (Grid/Layout)
.o-grid {
  display: grid;
  gap: @spacing-unit;
}

// 6. Components
.c-button {
  .flex-center();
  padding: (@spacing-unit * 2);
}

// 7. Utilities
.u-text-center { text-align: center; }

πŸš€ Build Setup (Modern Tools)

Vite + LESS

// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
        modifyVars: {
          'primary-color': '#3b82f6'
        }
      }
    }
  }
});

Webpack

// webpack.config.js
{
  module: {
    rules: [{
      test: /\.less$/,
      use: ['style-loader', 'css-loader', 'less-loader']
    }]
  }
}

🌐 Next.js Integration

// next.config.js
const withLess = require('@zeit/next-less');

module.exports = withLess({
  lessLoaderOptions: {
    javascriptEnabled: true,
    modifyVars: { '@primary': '#3b82f6' }
  }
});

πŸ“Š LESS vs SCSS Feature Comparison

FeatureLESSSCSS
Variables@var$var
Mixins.mixin()@mixin name()
Nesting&child&child
LoopsRecursive mixins@for/@each
If/ElseGuards (when)@if/@else
Modules@import@use/@forward
MathOperatorssass:math
Debug❌@debug

🎯 Complete Dashboard Example

// dashboard.less
@primary: #3b82f6;
@dark: #111827;
@spacing: 1rem;

.dashboard {
  min-height: 100vh;
  background: linear-gradient(135deg, #f8fafc, #e2e8f0);
  
  .container {
    max-width: 1200px;
    margin: 0 auto;
    padding: @spacing * 2;
  }
  
  .card {
    background: white;
    border-radius: 1rem;
    box-shadow: 0 10px 15px rgba(0,0,0,0.1);
    padding: @spacing * 2;
    
    &-header {
      .flex-center();
      border-bottom: 1px solid #e5e7eb;
      padding-bottom: @spacing;
      margin-bottom: @spacing;
    }
  }
  
  .stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: @spacing * 2;
  }
}

🎯 Production Checklist

βœ… [] Variables (@name) - Design tokens βœ… [] Mixins (.name()) - Reusable patterns βœ… [] Nesting (&child) - DRY selectors βœ… [] Operations (+ - * / %) - Dynamic sizing βœ… [] Guards (@when) - Conditionals βœ… [] Escaping (~β€œstring”) - Custom values βœ… [] 7-1 architecture - Organized structure βœ… [] Client-side compilation - Live reload βœ… [] Import strategies - Modular imports

🎯 Final Thoughts

LESS = Simple CSS superset. Cleaner syntax than SCSS, client-side compilation, rapid prototyping. Perfect for legacy projects, dynamic theming, and teams new to preprocessors.

2026 Strategy: LESS β†’ Legacy/Prototyping (25%) SCSS β†’ Enterprise systems (45%) Tailwind v4 β†’ Rapid dev (30%)

Build maintainable stylesheets with LESS’s lightweight power πŸš€.


LESS Official: lesscss.org | GitHub: github.com/less/less.js

Chat with us