Is it possible to load variables into LESS CSS preprocessor from a JSON file like you can do with Stylus?
With contents of file myvars.json
{
"color1": "#112345",
"color2": "#667890"
}
In Stylus I do...
json('myvars.json')
body{ background-color: color1; }
Is it possible to do this in LESS?
I want to keep the file as JSON, so I can easily re-use it in javascript.
In less.js you can make use of javascript interpolation (using the back-ticks). And call a function that loads the json object with the variables from the file ... from which you can extract the variable by its key - something in this direction perhaps:
@json_file: myvars.json;
@json: ~`json = function($key) { var request = new XMLHttpRequest(); request.open("GET", "@{json_file}", false); request.send(null); var my_json = JSON.parse(request.responseText); return my_json[$key]; }`;
body {
background-color: ~`json('color1')`;
}
this might not look super elegant, but it works. A more elegant option would probably be to define your custom user function in the global LESS object before calling the script, but I never really bothered playing with that, as I was always using LESS client-side just in development.
Another thing that you can do - is loading the json file in javascript (after calling the LESS script in the browser) and using the less.modifyVars()
function to recompile LESS with the json variables. You can do something along this lines in your html (here I use plain JS but it's even simpler if you use jQuery.getJSON):
<link rel="stylesheet/less" href="style.less" type="text/css">
<script type="text/javascript">less = { env: "development" };</script>
<script src="http://rawgithub.com/less/less.js/master/dist/less-1.4.1.min.js" ></script>
<script type="text/javascript">
var request = new XMLHttpRequest();
request.open("GET", "myvars.json", false);
request.send(null);
var my_json = JSON.parse(request.responseText);
less.modifyVars(my_json);
</script>
and something like this in your LESS style file:
@color1: darkblue; //default value - will get overwritten by .modifyVars()
body {
background-color: @color1;
}
Another note: all variable names in LESS have to begin with an at sign (@
). However, the json variables do not need to, because less.modifyVars()
automatically prepends the variables with an @
if missing.
Hope this gives you some ideas. There might be better ways to do it ... but this two approaches worked for me.
If you not use LESS in browser but compile the CSS, I just publish a gulp plugin to do this job.
It can look like this :
css/myvars.json
{
"color1": "#112345",
"color2": "#667890"
}
less/styles.less
@json-import "myvars.json";
body {
background-color: @color1;
}
gulpfile.js
var gulp = require('gulp');
var less = require('gulp-less');
var lessJsonImport = require('gulp-less-json-import');
gulp.task('less', function(){
gulp.src(['./less/**/*.less', '!./less/**/_*.less'])
.pipe(lessJsonImport())
.pipe(less())
.pipe(gulp.dest('./css'));
});
When using LESS in browser, there is also 'globalVars' option that can be used to set variables before loading the LESS files: http://lesscss.org/usage/#using-less-in-the-browser-options
You can use globalVars
less option to provide object loaded from json file.
For example with less-loader plugin webpack.config.js
will be like:
function lessGlobalVars() {
return require('flat')(require('./path/to/config.json'),
{
delimiter: '_'
});
}
module.exports = {
module: {
rules: [
{
test: /\.less$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
options: {
globalVars: lessGlobalVars()
}
}
]
}
]
}
};
config.json
:
{
"dimensions": {
"width": 100,
"height": 50
}
}
globalVars
accepts only flat structures so we need flat package that will flatten object loaded with require('./path/to/config.json')
to:
{
dimensions_width: 100,
dimensions_height: 50
}
Passing this object to globalVars
option will make global variable @dimensions_width
and @dimensions_height
available for all your less stylesheets:
.some-class {
width: @dimensions_width;
height: @dimensions_height;
}