Reputation: 185
Sometimes it's necessary to set some constants twice: in SASS and in JS (for better performance for example). Is anyone knows solution for synchronizing SASS/SCSS and JavaScript variables to have access to SCSS variables from JavaScript or from SASS to JavaScript?
Upvotes: 3
Views: 2654
Reputation: 1601
In case you are using webpack and CSS Modules and SASS (for example with React), you can just use :export pseudoselector, as described here or here
Upvotes: 0
Reputation: 40698
You could try writing JSON in a SASS/CSS comment block:
/*
{
"blue" : "#{$blue}",
"green" : "#{$green}"
}
and then extract and parse it on the client.
Upvotes: 0
Reputation: 195
I know this was asked almost a year ago, but I'm putting this answer up as a reference for the next poor sod who has this problem. There are probably better solutions out there, but this one is the only thing I could find/come up with.
Since JavaScript doesn't seem to be able to get variables from any .scss
file directly, we have to use regex to get the desired value from our file. But since we don't want to make it search though our entire SASS file:
We create a new file, _variables.scss
, for JavaScript to search through. Let's say it looks like this:
$menuMobileArrowRotate: 90;
$articleScale: 1.1;
Import it to SASS by adding @import "variables";
near the top of our stylesheet. We can then use these variables throughout our file instead of manually entering values.
I'm going to get JavaScript to read _variables.scss
and turn it into a string:
var sassVariables = new XMLHttpRequest();
sassVariables.open("GET", 'http://www.use-absolute-url.com/_variables.scss', false);
sassVariables.send(null);
Note: to support IE6 and earlier, replace var xmlhttp = new XMLHttpRequest();
with:
if (window.XMLHttpRequest) {
var sassVariables = new XMLHttpRequest();
}
else {
var sassVariables = new ActiveXObject("Microsoft.XMLHTTP");
}
If I set asynch. to true
, Firebug shows me an error claiming that fileContent
doesn't exist. And since my file is only 4KB, I'm not going to worry too much about potential performance problems by having to wait for it to load.
Now, I'm going to declare my variables:
var fileContent = sassVariables.responseText, //a string holding the contents of my file
menuMobileArrowRotate = null,
articleScale = null;
I declared menuMobileArrowRotate
and articleScale
before I made sure the file actually loaded, since I don't want JavaScript to give me an error and mess everything up just because it didn't load.
If everything loads fine, I'm just going to use RegEx to find out the value of each of my variables. At least I'm only going through a tiny file instead of searching through my entire stylesheet.
if (sassVariables.status === 200) { //if everything loaded nice and dandy
menuMobileArrowRotate = fileContent.match(/(?:menuMobileArrowRotate.\s*?)(\d+)/)[1];
articleScale = data.match(/(?:articleScale.\s*?)((\d+)\.*(\d+)*)/)[1];
}
Notice the [1]
after .match()
: RegEx returns an array, and I only want the first match (which, in my case, is also the only match).
For all the JS put together:
if (window.XMLHttpRequest) {
var sassVariables = new XMLHttpRequest();
}
else {
var sassVariables = new ActiveXObject("Microsoft.XMLHTTP");
}
sassVariables.open("GET", 'http://mysite.com/sass/_variables.scss', false);
sassVariables.send(null);
var fileContent = sassVariables.responseText,
menuMobileArrowRotate = null,
articleScale = null;
if (sassVariables.status === 200) {
menuMobileArrowRotate = fileContent.match(/(?:menuMobileArrowRotate.\s*?)(\d+)/)[1];
articleScale = fileContent.match(/(?:articleScale.\s*?)((\d+)\.*(\d+)*)/)[1];
}
console.log(menuMobileArrowRotate); //shows 90
console.log(articleScale); //shows 1.1
I can now use these variables anywhere in my JavaScript file following this bit of code.
SASS doesn't let you use a variable in a media query. However, I can make the whole dang query a mixin, and put it in _variables.scss
:
@mixin mediaQuery($point) {
@if $point == 'mobile' {
@media only screen and (max-width: 600px) { @content; }
}
@if $point == 'somethingElse' {
@media only screen and (max-width: 1000px) { @content; }
}
}
In style.scss
, I can have:
@include mediaQuery(mobile) {
//blah
}
@include mediaQuery(somethingElse) {
//blah
}
I can then use the same process to get the desired values (i.e. 600 and 1000), just with different RegEx.
Upvotes: 2