Chat with Less.js users and contributors
This is the Less.js monorepo, managed via Lerna.
More information
For general information on the language, configuration options or usage visit lesscss.org.
Here are other resources for using Less.js:
- stackoverflow.com is a great place to get answers about Less.
- Less.js Issues for reporting bugs
Contributing
Please read CONTRIBUTING.md. Add unit tests for any new or changed functionality. Lint and test your code using Grunt.
Reporting Issues
Before opening any issue, please search for existing issues and read the Issue Guidelines, written by Nicolas Gallagher. After that if you find a bug or would like to make feature request, please open a new issue.
Please report documentation issues in the documentation project.
Development
Read Developing Less.
Release History
See the changelog
Contributors
Code Contributors
This project exists thanks to all the people who contribute. [Contribute].
License
Copyright (c) 2009-2017 Alexis Sellier & The Core Less Team Licensed under the Apache License.
The way Extend works - more complicated selectors and change in matching
From @DesignByOnyx
I have finally gotten around to testing this and wanted to post my initial findings. I have been using the alpha version less-1.4.0-alpha.js on the client-side only (no command line yet - not that it should be any different really).
So far, everything works as I would expect except for two major drawbacks which can be explained with one example. Take the following code which is located in one of my root LESS files:
Issue 1 - styles defined within media queries do not get extended. Anything trying to extend the .container class only gets the margin: 0 auto styles.
Issue 2 - compound selectors do not get extended. However, the first participant DOES get extended. For example, the following incorrectly extends the .container styles but not the intended .container.positioned styles.
I wish I could provide a solution. Hope this helps.
Allow parametrized mixins as detached rulesets to form 'lambdas'
It seems that currently LESS only supports 'pure' rulesets to be passed along as mixin arguments or stored in variables as detached rulesets.
I suggest to extend this support to incorporate parametrized mixins, essentially giving LESS the capability to work with lambdas.
E.g. One would be able to write
where
.forEach
is defined asLambda mixin support would also neatly resolve recurring issues with function return arguments and the ugly hack where variables 'bubble up' to parent scope if said variables are as of yet undefined in said parent scope.
The suggested practice could become to adopt continuation style programming; passing 'return values' along into a lambda mixin to continue down the scope chain. This kind of mechanism is more transparent to users, less brittle by avoiding issues with potential variable name collisions and just fits in better with the overall functional programming paradigms that the LESS syntax is built on.
[EDIT] Having just had a look at the way detached rulesets and calls are implemented in the AST, I think very little needs to happen to make this work. Even on the parser side of things, it seems fairly simple to just parse an optional block of
mixin.args
beforeblockRuleset
in thedetachedRuleset
parser function and pass the arguments along to thetree.DetachedRuleset
node instance. (Thetree.DetachedRuleset
would need to be extended with the params evaluation fromtree.mixin.Definition
, ofcourse.)variable in @import statement
The lastest version introduced the possibility to "access the value of an abstract property from a string using { } operators" (section "String interpolation" in http://lesscss.org/#-string-interpolation).
But the problem is that it doesn't work in import statements. It would be great to write code such like this :
//define the template @mainTemplate: "BaseTheme";
//import the template @import "_templates/@{mainTemplate}/Config/_ConfigTemplateDefault.less";
I don't know if it is possible to resolve this issue, but it would be great !
How to handle Maths
See #1872
Possibility to add another case for calc which like font, with strict mode off, essentially turns strict mode on for a rule ? Too many exceptions in the future?
@seven-phases-max : Well, there're a lot of other possibilities, e.g.
./
or require parens for division (e.g.1/2
->1/2
but(1/2)
->0.5
) etc... Also, the "special cases" (e.g. properties wherex/y
can appear as shorthand) are not so rare (starting atpadding
/margin
and ending withbackground
/border-radius
and eventually there can be more) so we just can't hardcode them all like it's done forfont
(and because of that I think that the current font "workaround" is just a temporary and quite dirty kludge that ideally should be removed too).Version 3.10.x uses significantly more memory and is significantly slower than 3.9.0
Our builds recently started failing because we run about 80 Less builds in parallel during our project's build process and the new version of Less.js uses so much memory that Node crashes. We traced the crash to upgrading from Less.js from 3.9.0 to 3.10.3.
I changed our Less script to compile the files sequentially (building 2 files at a time) and sampled Node's memory usage during the process and got the following results:
Less.js seems to use 130% more memory now and takes about 100% longer to compile for us.
Just wondering if you've benchmarked Less.js and whether you see similar results
Public variables on namespaces
I realize this isn't a new topic but it I think the time has come to consider implementing public variables on namespaces. Many prominent libraries for LESS (bootstrap, hat, etc.), have emerged, each with dozens of configuration variables which could very well overlap and conflict with each other.
Currently, namespaces support private variables, the only way to get at them is via mixins within the namespace and those mixins can then be used externally; Sort of like a closure:
Which yields:
However, I think it would be very handy to do the following:
As well as update those variables within the namespace:
Add Sass like extend
Sass extend is here. http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#extend
More simple syntax, use +.
converted this.
See also test code.
Support file globbing for @imports
See: https://github.com/isaacs/node-glob, and ~~https://github.com/isaacs/minimatch~~ https://github.com/jonschlinkert/micromatch
I use these often in projects. It would be pretty awesome to be able to do the following and not have to specify individual files:
After only a few minutes of using these patterns they become second nature. It might even help with some of the other import issues.
Implemented via plugin: less-plugin-glob.
Import options
We have decided that the best way to handle the import bugs is by having options.
Given the scope of the bugs I feel strongly that the options need to be inline with the actual import statement
I suggest removing
@import-once
and@import-multiple
and allowing options to be passed to the@import statement
Note that import can already be followed by media statements e.g.
The options I propose we support are
?.css
onto the end of url's at the moment to treat as css - a bit of a hack@import-multiple
though not so important if we want to dropso here are some options.
downsides are its a bit confusing with the media query syntax. we could also put the options second and mix them with the media query, defining our own special media query options essentially, but I don't like that in case we conflict in the future with css.
from @jonschlinkert
and variations on the above, such as using closer media query syntax like
I initially disliked @jonschlinkert's options idea, but it does actually allow for setting defaults.. what I don't like is that it looks a bit verbose.
we could also assume
:true
and haveand I am open to any other suggestions.
Mixins should accept LESS blocks
It would be helpful if mixins had access to a content block passed to them, so one could encapsulate media queries or browser hacks in a central place and reference them symbolically.
This is basically the "Passing Content Blocks to a Mixin" feature of SASS: http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixin-content
In LESS this would mean something like:
Class constructor FileManager cannot be invoked without 'new'.
It seems that v3.10.0 breaks my build, webpack logs below:
Everything is ok when downgrade to v3.9.0, please investigate this issue and hope to fix it as soon as possible.
Remove PhantomJS stuff
I saw this and though, nobody is using phantomjs. it's a headless browser that no real user is using. it was based on webkit and the development have been discontinued. think you should remove this kind of things and instead use something like puppeteer or something.
https://github.com/less/less.js/blob/eefe33a47f6fdcc228817df7435a1770ce9e51ea/packages/less/src/less-browser/index.js#L49-L56
PhantomJS is depricated and should not be used anymore.
Global Variables with a literal "." in the value causes the variable to be undefined
To reproduce: This can be reproduced using the CLI or the programmatic API. Assuming that LESS is already installed, it is most straightforward to reproduce using the CLI:
On the other hand, removing the literal period allows this to work:
LESS Code:
Current behavior: The LESS compiler throws an error that the global variable is undefined.
Expected behavior: The LESS compiler should not throw an error and the global variable should be defined.
Environment information:
less
version: 3.5.0 - 4.1.3 (current)nodejs
version: 16.13.2operating system
: WindowsAppears to have been introduced in 3.5.0. Version 3.0.4 appears to be working fine.
Support for recently added CSS functionality container-queries
As pointed out by @treponat, it seems support for
@container
queries should be implemented in less.By tomorrow (12/12/2022) Firefox will release 108 with support for container queries, completing all the major browsers support for the feature.
Discussed in https://github.com/less/less.js/discussions/3759
Originally posted by treponat November 3, 2022 Recently some of the browser started to support a new feature that would allow to create responsive design based on the parent element rather than client's viewport. https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries It would be wonderful if LESS would also start to fully support this feature. Currently you can use container functionality in .less files, but the hierarchical structure of css blocks is not working as expected for the container syntax. for example
would produce this css blocks
instead of
Nested @media blocks are combined in a non-compliant way.
According to the CSS spec, media type (
screen
,print
etc) must be first on the list and all the other conditions (for example(max-width: 800px)
) must follow after the media type.To reproduce:
Current behavior:
Less compiler combines nested media conditions in a way that is not compliant with the spec, putting media type between conditions or after them.
Expected behavior:
Media type should be put into the first position in the media query, like so:
Environment information:
less
version: 4.1.3, including the official playgroundnodejs
version: anyoperating system
: anyAdditional notes
Even though it might seem trivial to re-order the example above to produce correct results, it's not always possible since the inner
@media screen
might come from a third party (I'm working withantd
) that I can't modify.It seems like most browsers don't mind media conditions being out of spec (or I didn't observe the effects), however this issue prevents me from using https://parceljs.org/ which implements pretty strict standards checking and chokes at the less output, producing
Unexpected token Ident("screen")
. The fixed snippet where media-type comes first is processed correctly byparcel
.allow image-size accept Url parameter
What:
image-size
,image-width
,image-height
can accept parameter likeurl(a.png)
Why: I can write code like
else I have to write:
How:
Checklist:
fix faulty source map generation with variables in selectors
Note to reviewer: There are two potential solutions here, one that fixes the specific issue linked, and one that might be a bit more robust. Filter down to the first commit for the bandaid fix, second commit for the more robust one, third commit for added test. I recommend hiding whitespace changes in the GitHub UI – my editor removed a bunch of unnecessary trailing spaces
PR Template
What:
Fixes https://github.com/less/less.js/issues/3567
Source maps are pointing to the wrong files, and it seems that it points at different files on different runs, causing non-deterministic source map output.
Checklist:
Why and How are included in the below description, which details the problem in the code and the proposed solutions.
Investigation and the problems
Bear with me a bit, this was my first venture into the less source code 🙂
We were seeing that we got weird source map output, mapping to files that shouldn't even appear in the source maps (e.g. reference imports from which nothing was used). After digging, there are a couple of problems that are causing this whole issue.
Background information
I was able to narrow down my search a bit by finding when this bug was introduced. It was released in
3.5.0-beta.2
, and the bug was introduced in https://github.com/less/less.js/pull/3227.We were seeing this happen when a selector included a variable, which directed me to this bit: https://github.com/less/less.js/pull/3227/files#diff-d8c0204835f49ae90096efe1e2d0d80868e0e6214bfd4c960a097eb20cc14ec9R67-R83
It looks like what this is doing is recreating the selector CSS with the "variableCurly" node replaced with the variable's value. Then it parses that newly created CSS, and replaces the old
Selector
node(s) with the new one(s). It looks like the code is trying to preserve source information by passing in thefileInfo
andindex
of the original selectors toparseNode
: https://github.com/less/less.js/blob/eefe33a47f6fdcc228817df7435a1770ce9e51ea/packages/less/src/less/tree/ruleset.js#L85-L86For a little more context, my understanding is that
parseNode
is used for creating new nodes after the original input files are parsed.First problem
In
parseNode
, the providedcurrentIndex
andfileInfo
are added to the newly created node(s) here: https://github.com/less/less.js/blob/eefe33a47f6fdcc228817df7435a1770ce9e51ea/packages/less/src/less/parser/parser.js#L111-L112These lines assume that
result
is a tree node. However, in some cases,result
is actually an array of nodes. So when it tries to add the source info from the old selectors to the new ones, it's actually just setting_index
and_fileInfo
properties on the array itself, so it doesn't actually ever make it to the source maps. In this case, theparseList
is["selectors"]
, soresult
is an array ofSelector
tree nodes.Second problem
Selector
nodes have anelements
array, containing the elements that make up the selector. When aSelector
is added to the output, it actually does so by generating the CSS for each of its elements: https://github.com/less/less.js/blob/eefe33a47f6fdcc228817df7435a1770ce9e51ea/packages/less/src/less/tree/selector.js#L135-L138This means that if the
_fileInfo
or_index
for the Selector's elements is incorrect, then the output source map will be incorrect. That also means that even if the_fileInfo
and_index
were correctly set on theSelector
(s) rather than the array containing theSelector
(s), the source maps would still be incorrect on theElement
s that make up the selector. The source info for the elements gets set here: https://github.com/less/less.js/blob/eefe33a47f6fdcc228817df7435a1770ce9e51ea/packages/less/src/less/parser/parser.js#L1299There are two problems here:
currentIndex
passed intoparseNode
doesn't get added to the createdElement
s indexfileInfo
is not thefileInfo
that gets passed intoparseNode
. It's thefileInfo
that's given to theParser
when it's instantiated: https://github.com/less/less.js/blob/eefe33a47f6fdcc228817df7435a1770ce9e51ea/packages/less/src/less/parser/parser.js#L41The proposed solution(s)
I have two proposals for how we can solve this. One is more of a bandaid fix, and the other is (I believe) a bit more robust. Both solutions include the fix for where
_fileInfo
and_index
get set on an array.elements
for each selector returned byparseNode
, and update the_fileInfo
and add thecurrentIndex
to the_index
for each one.this.parse.parseNode
and relying onparseNode
to update the_index
and_fileInfo
of the created nodes, create a newParser
object each time we want to callparseNode
. This removes thecurrentIndex
andfileInfo
params forparseNode
, and adds acurrentIndex
param to theParser
itself. All nodes created by the parser will addcurrentIndex
(which defaults to 0) to the index fromparserInput
. This way, we can ensure that any nodes created withparseNode
will have the correct source information.The first proposed solution can be seen by filtering to the first commit, and the second proposed solution can be seen by filtering to both the first and second commits. The third commit adds a test to ensure that selectors with variables in them have properly generated source maps. I recommend hiding whitespace changes in the GitHub UI – my editor removed a bunch of unnecessary trailing spaces.