Change LESSCSS variable with jQuery
Instead of dinamically changing values in your less file - which is impossible on the client side (aka JavScript), try creating multiple variants in less (something like a theme), and then apply a custom class to an element (body works well).
For example,
[style.less]
@green: #00EE00;
@blue: #0000EE;
body {
&.green { background:@green }
&.blue { background:@blue }
}
[main.js]
$('#id').on('click', 'a.blue', function() {
$('body').removeClass('green').addClass('blue')
}
Javascript library for editing LESS CSS variables?
I've come across this problem often lately and after trying many things my solution is to eventually ditch LESS and go with Stylus, which has a nice JavaScript API.
In any case, this is what I have working right now to get LESS variables in JavaScript:
var getLessVar = function (name, prop) {
var value = $('<div class="' + name + '"></div>').hide().appendTo('body').css(prop)
$('.' + name).remove()
return /^\d+/.test(value) ? +value : value
}
It's hacky but works. You create a class in LESS and assign the variable you want to get in JS to a property, let's say width
, but it can be any other property, depending of the type of data you're sending (numbers, colors...)
@myvar: 30px + @foo;
.myvar { width: @myvar }
Then in JS you grab the variable with that lil' script like this:
var myvar = getLessVar('myvar', 'width')
This is not great for performance as it creates an invisible element to retrieve the data but it works.
To set a variable from JS is more complicated, but you can always do some AJAX magic together with LessPHP
and some basic parser to read your variables.less
.
But again, if you need more power just go with Stylus.
dynamically change LESS variables in page with JavaScript
Instead of doing the variable replacing client-side, since I was doing it in a Rails app anyway, I moved it server-side. I'm using the Ruby bindings for LESS to parse some LESS that includes my custom variables, rendering the parsed result with content_type: 'text/css'
and using an AJAX request to add a stylesheet link to the rendered CSS.
Less CSS precompute number and append unit
Try the following:
(100/300)*1%
Less only accepts values and not strings so you cant just add a string after a number but you can multiply with a percentage to archieve the same.
Output nested selectors as individual lines with LESS
I found that if I just structured it like this, without the commas, I get the desired outcome.
.newsletter-form input {
&::-webkit-input-placeholder {
color: red !important;
}
&::-moz-placeholder {
color: red !important;
}
&:-ms-input-placeholder {
color: red !important;
}
}
Or using a mixin for flexibility.
.placeholder(@color) {
&::-webkit-input-placeholder {color: @color !important;}
&::-moz-placeholder {color: @color !important;}
&:-ms-input-placeholder {color: @color !important;}
}
.newsletter-form input {
.placeholder(red)
}
Compile a referenced LESS file into CSS with PHP automatically
THIS ASSUMES LESSPHP v0.3.8+ Unsure about earlier versions, but you'll get the gist of how it works if it doesn't straight out of the box.
<link rel="stylesheet" type="text/css" href="styles/main.less" />
If you were using less.js to compile client side, make sure you change rel="stylesheet/less"
to rel="stylesheet"
1) Grab Lessphp I placed these files in /www/compilers/lessphp/
for the context of this demo
2) Make a PHP script that we can throw out LESS files at. This will deal with caching, compiling to CSS and returning the CSS as a response. I have placed this file at /www/compilers/
and called it lessphp.php
Most of this code was on the Lessphp site, except there were errors in it, and I have added the response at the end.
<?php
require "lessphp/lessc.inc.php";
$file = $_GET["file"];
function autoCompileLess($inputFile, $outputFile) {
// load the cache
$cacheFile = $inputFile.".cache";
if (file_exists($cacheFile)) {
$cache = unserialize(file_get_contents($cacheFile));
} else {
$cache = $inputFile;
}
$less = new lessc;
$less->setFormatter("compressed");
$newCache = $less->cachedCompile($cache);
if (!is_array($cache) || $newCache["updated"] > $cache["updated"]) {
file_put_contents($cacheFile, serialize($newCache));
file_put_contents($outputFile, $newCache['compiled']);
}
}
autoCompileLess('../' . $file, '../' . $file . '.css');
header('Content-type: text/css');
readfile('../' . $file . '.css');
?>
This will compile the LESS file (eg, styles/main.less
) to a cache file and a CSS file (eg, styles/main.less.css
).
3) Add a mod_rewrite
rule so that any LESS files a user requests are redirected to our compiler, giving it its path. This was placed in the root .htaccess
file.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^([^.]*\.less)$ compilers/lessphp.php?file=$1 [R,QSA,L]
</ifModule>
If you are using WordPress, this rule will need to come after it - even if WordPress is in a sub directory, it seems to overwrite these rules, and LESS compilation will not occur for referenced files which exist below (directory wise) WordPress's .htaccess
rules.
4) Your LESS code should be relatively referenced in relation to the compilers location. Additionally, Lessphp compiler will fail if there are empty attributes, eg. background-color: ;
If all is working well, the following should occur:
Directly browse your LESS file
http://domain.com/styles/main.less
Be automatically redirected to
http://domain.com/compilers/lessphp?file=styles/main.less
Be presented with minified CSS
main.less.css
andmain.less.cache
should now exist in the same directory as your LESS fileThe last modified dates shouldn’t change unless you update your LESS file
Access CSS file contents via JavaScript
you could load the content with a simple ajax get
call, if stylesheet is included from the same domain
Edit after your update:
I tried this code (on FX10) as a proof of concept that uses only one request to the CSS but it seems a bit hacky to me and should be tested and verified. it also should be improved with some fallback if javascript is not available.
CSS (external file test.css)
div { border: 3px solid red;}
HTML/jQuery
<!doctype html >
<html>
<head>
<!-- provide a fallback if js not available -->
<noscript>
<link rel="stylesheet" href="test.css" />
</noscript>
</head>
<body>
<div></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.js"></script>
<script>
$(document).ready(function() {
$.when($.get("test.css"))
.done(function(response) {
$('<style />').text(response).appendTo($('head'));
$('div').html(response);
});
})
</script>
</body>
</html>
You should see the CSS code inside the div with a red border all around :)
Enjoy.
Related Topics
JavaScript Beforeunload Detect Refresh Versus Close
When Loading an HTML Page via Ajax, Will Script Tags Be Loaded
How to Disable Copy Paste (Browser)
How to Get a Floating Footer to Stick to the Bottom of the Viewport in Ie 6
How to Use Materialize-CSS with Angular
Detect Inside Android Browser or Webview
How to Get the Browser to Navigate to Url in JavaScript
How to Get "Get" Request Parameters in JavaScript
Cannot Use Attr with an Object in D3 V4
How to Listen/Detect Changes to an Input Value - When the Input Value Is Changed via JavaScript
How to Save and Restore a File Object in Local Storage
How to Detect Support for the HTML5 "Download" Attribute
How to Stop User from Printing Webpages? Using JavaScript or Jquery
How to Apply CSS to Only Numbers in a Text Inside/Or Any <P><P> Element