Skip to main content

Migrating Less 4.x → 5.x

Coming to Jess from Less 4.x? Jess is the engine behind Less 5.x, so the same breaking changes apply when you move existing Less sources onto Jess. This page lists the ones that most often need attention.

Removed: inline backtick JavaScript

Inline backtick JavaScript is removed entirely. It is now a parse error — not a flag you can opt back into.

// No longer valid — this is a parse error:
@columns: `Math.max(12, 8)`;

In Jess there is no inline-JavaScript syntax at all. Move any scripted values to a module you pull in with @-use, or express them with built-in functions (@columns: max(12, 8);).

Imports

Jess's module system is @-compose (namespaced import, isolated scope, with { } configuration). In .jess a bare @import is always a plain CSS at-rule (passed through — no extension heuristic); it is never a source include. To fold a stylesheet in and evaluate it, use an explicit dash-prefixed rule: @-compose (preferred) or @-import (mechanical port; warns). The compiler at-rules require the dash — bare @use/@compose are not valid Jess.

// CSS @import (passed through), NOT a source include:
@import "foo";

// Legacy source include (warns) — prefer @-compose:
@-import "./foo.less";

// The module system:
@-compose "./foo.less" as foo;

See Modules & imports.

CSS nesting is preserved by default (collapseNesting: false)

Less 5.x has first-class CSS nesting, and it keeps nested structure by default (collapseNesting: false). Output stays in the familiar nested shape unless you explicitly opt into collapsing.

.card {
padding: 1rem;
.title { font-weight: 600; }
}

By default this compiles to nested CSS (.title stays nested under .card). Enable collapseNesting: true for the older flattened (.card .title { … }) output when you need deduplication or wider tooling support.

If you are porting a 4.x project that assumed flattened output, set collapseNesting: true while you migrate, then move to native nesting once your toolchain supports it.

Less-style parent-suffix composition still works, and the parent-template model is now explicit:

  • &-1 composes a suffix onto the parent (.col { &-1 {…} }.col-1).
  • &() keeps the parent selector but hoists the nested selector to root.
  • &('') drops the parent selector entirely.
  • &(-1) is equivalent to &-1.

extend and the !all flag

extend behavior is validated against fixture parity, including nested and media-scoped selectors. Per-selector all in multi-target extends is deprecated in favor of a single !all flag:

// Deprecated:
&:extend(.a all, .b all);

// Preferred:
&:extend(.a, .b !all);

With collapseNesting: true, extend … !all in nested selector-list cases may emit :is(…) selectors to reduce duplication.

Variable resolution follows source order

Less 4.x had eager-resolution edge cases where a later mixin call could appear to retroactively change an earlier declaration. Less 5.x resolves declarations in source order against the scope that exists when they are evaluated — a later side effect does not rewrite an already-evaluated sibling declaration.

@mix: blue;
.mixin() { @mix: #989; }
.tiny-scope {
color: @mix; // blue — resolved before .mixin() runs
.mixin();
}

Math modes

  • Move strictMath workflows to the math option.
  • strict-legacy math mode is removed.
  • math=always is deprecated; treat it as legacy behavior.
# old
lessc --math=always styles.less styles.css
# preferred
lessc --math=parens-division styles.less styles.css

Deprecated CLI / option paths

  • --relative-urls--rewrite-urls=all (or rewriteUrls).
  • --ie-compat is a no-op in modern pipelines.
  • built-in compress → use a dedicated CSS minifier.
  • dumpLineNumbers / --line-numbers → use sourcemaps.
  • strictImports is deprecated; avoid it in new configs.

Runs on the Jess engine

Jess is the engine. Less 5.x is Jess with the Less-compatibility surface turned on, so the evaluation model described throughout these docs is exactly what your migrated Less sources run against.