Ideally, I'd like to set up one file "colors.styl" where I can define all the colors used across the site like so:
// --------------- GENERAL VARIABLE DEFINITIONS
$beige = #F2F2F2
$darkGrey = #282828
$errorRed = #B94A48
When I try accessing these variables in other files, I just get the variable name back instead of the resolved value:
body {
background-color: $beige;
I'm compiling the files in order so colors.styl goes before the rest. Do variables lose their scope across files in Stylus?
Instead of doing #import "colors" in every file, you can also make a main loader file, like this:
#import "colors"
#import "styles1"
#import "styles2"
Variables defined in colors.styl will then be available in styles1.styl and styles2.styl. Output from stylus will be one big css file containing all your styles.
Yes, variables lose their scope across files.
But you can #import color in the other files to access the variables.
Related
First of all, I hope someone can actually understand this rambling question because I'm struggling to even word what I mean in a coherent way, but here goes:
I don't know why I'm struggling so much to figure this out, but I've been using #import with SCSS for a while now and feel I have my head around it fairly well, but now I want to use the #use rule since the phasing out of #import is a thing. And I can't find any videos or any real articles explaining how to use it properly.
The problem I'm having is I can't get my head around how to actually use it, I feel like I get the basic idea, and how to use the modules in each partial (I think..), but I feel like I don't understand how to actually get all of the partials into a main .scss file to be compiled into css.. This is hard to explain.. I just feel like I would still need to #import at least the files that have #use inside them into a main file for it to be compiled.. I'm guessing this obviously isn't the case, but otherwise I can't work it out.. Do I just #use all the files I want imported into the main file or..?
If anyone could shed some light on this for me, I would be really grateful.
Thanks
The new rules #use/#forward and the remove from #import are indeed a really big impact to SASS. It leads to a complete new form to write sass. A try to make an easy explanation for the beginning to use the new technique:
(1) #use works similar to #import. It adds the code from a (config- or partial-)file or a module to your stylesheet.
(2) The difference is: SASS changes the scope of variables/mixins/functions from global (all imported files = one scope) to local files (variables are only valid in the actual file). If you need to use variables/mixins/functions from another (config- or partial-)file you need to 'include' them to the actual file first.
That means for your project(*):
//file ###> _config.scss
$columnWidth: 50%;
$projectColors: (
primary: red,
secondary: blue,
);
//file ###> _functions.scss
#use 'config' as * // --> to use config vars (here: without namespace)
#function getColor( $name ){
$color: map-get($projectColors, $name);
#return $color;
}
//file ###> _partial.scss
#use 'config' as * // --> use config vars (here: without namespace)
#use 'functions' as * // --> use functions (here: without namespace)
.class {
width: $width;
color: getColor( primary );
}
//file ###> myStylesheet.scss
// no need to #use 'config' or 'functions'
// as they are not direct needed in this file
#use 'partial' //--> write the css
---
( * ) Including files without using a namespace is a special case to make the example more easy. Normaly you will include variables/mixins/functions to a separated namespace and call them by namespace.$variable or namespace.mixin. And there are techniques to move special settings to a #used file as well so you can move variable settings to the project. Please have a look to official and excelent description: https://sass-lang.com/documentation/at-rules/use
NOTES:
(1) As it is heavily discussed: Yes. This is INDEED the intended new way to work with SASS. (https://github.com/sass/sass/issues/2750)
(2) Very interesting: The actual brandnew version from Bootstrap has moved to the new Sass Version. But as I have seen Bootstrap does not use that new feature #use and still works with #import. That may have reasons ... and it seems not to easy to change the technique.
(3) Also it seems to be a little bit complicated there are some advantages comming with that new technique. Using separate namespaces make it much mor easier to work with external modules without causing name conflicts.
I've been using Sass's new module system for a while now, and for the most part have grokked how it works. One use case that I can't work out how to translate from the old system to new however is how to produce mostly identical stylesheets with only minor variations and configuration changes—for the purposes of localisation.
(CSS Custom Properties unfortunately aren't really an option for this. That would make this way easier!)
In the past, I've achieved this by having an entry file for each locale, with the configuration info for that locale, which could be grabbed by all the following imported files and make whatever locale-specific manipulations it needs to. For example:
en.scss
$locale: "en";
$rtl: false;
$font-family: "Gill Sans", sans-serif;
#import "shared/code";
ar.scss
$locale: "ar";
$rtl: true;
$font-family: sans-serif;
#import "shared/code";
When processed I'd end up with an en.css file with only the CSS that English requires and an ar.css file with only the CSS that Arabic requires, and all is good.
This is no longer possible in the Sass module system. Because an explicit aim of the module system was to remove global variables and more tightly scope things to individual files, #import has been deprecated in favour of #use and #forward, neither of which allow "children" access to the variables of the "parent" file.
My first thought was to lean into the module system and create an importable configuration file for each locale. Doing something like this works:
#use "locale/en" as locale;
html {
font-family: locale.$font-family;
}
However, now my locale reference is hardcoded into every file that requires it. #use only accepts a string (no variables), so I can't try and be clever with it, and I can't generate CSS for multiple locales without editing several files first. Fail.
My current hack-y solution is to #use "config"; everywhere, store my locale variables in a bunch of different configuration files, and then change the name of a locale file to "config" when I need to compile for that locale. This is obviously unsustainable and prone to human error a-plenty, so I'd like a second opinion on if there's some other method of doing this that has just completely passed me by, or whether this use case just isn't possible under the new Sass module system anymore.
Thanks in advance!
This is the purpose of with (...) configuration in the module syntax. The importing file is still able to configure variables in the loaded module - that just happens with a more explicit syntax:
// en.scss
#use "shared/code" with (
$locale: "en",
$rtl: false,
$font-family: ("Gill Sans", sans-serif),
);
and:
// ar.scss
#use "shared/code" with (
$locale: "ar",
$rtl: true,
$font-family: sans-serif,
);
We have a LESS based stylesheet for which we would like to generate multiple color variations. We have defined an include file which contains the color variations (for now blue.less) and would like to generate and use green and red variations of this include file.
What we would like to do is to somehow parametrize less via the command line to include one of these specific color files. Does anybody know how this can be done?
Put the color definitions into variables in a separate file, eg. blue.less:
#baseColor: #0000ff; // blue
#accentColor: #00ffff; // yellow?
then create a separate theme file, eg. theme.less, where you define how the base color should be changed to achieve your theme:
#link-color: #baseColor;
#link-hover-color: darken(#link-color, 15%);
#panel-header-highlight-color: darken(#accentColor, 15%);
...
then in a third file, e.g. layout.less, you define
a {
color: #link-color;
&:hover {
color: #link-hover-color;
}
}
...
finally, create your blue-master.less:
#import "blue.less";
#import "theme.less";
#import "layout.less";
To create a red-master.less you should only need to write a color file and change one line in the above.
You can call the color-file color.less, and e.g. have a blue/color.less and a red/color.less, and use the --include-path=.. parameter to lessc to make it generate different files based on command line parameters, but I would advise against it (it becomes much more arduous to work with in my experience).
I have a Sass file which does multiple imports as follows
#import("variables")
#import("custom-variables")
#import("widgets")
#import("custom-styles")
I declare a variable called $promoBoxColor for example in both variables and custom-variables, and then the widgets and custom styles references this variable.
What I am finding is that the color defined in variables is being used if I try and use it in custom-styles, not the colour defined in custom-variables.
Is it possible to override variables in this way in Sass? It seems to work fine if I just override a color used in widgets.
Thanks for the replies. Found the best way of doing this was to set all the variables in the core variables file with !default and then declare the custom-variables first.
Is it possible to set a sass variable at compile time? I basically want to do this:
$color: red !default;
div#head {
background-color: $color;
}
When I compile to css I want to set $color to "blue" (preferably from the command line). Has anyone been able to do this?
Thanks,
Chris
I found this at their FAQ http://sass-lang.com/docs/yardoc/file.FAQ.html
If you just want to pass some variables to the CSS every time it gets compiled, like using --watch, you can use Sass functions to define Ruby scripts to even query a database. But the code is going to be compiled only once, and served statically.
But if you need to recompile it at every request with different options,
you can use Sass::Engine to render the code, using the :custom option
to pass in data that can be accessed from your Sass functions
Seems like it's not recommended, though. Probably for performance reasons.
An alternate of command line options is to create other files assigning values to variables.
Assume that your code above is in a file named 'style.scss'.
To set $color to "blue", create a file such as:
$color: blue;
#import "style";
and name it to 'blue.scss' for example.
Then compile it with below.
sass blue.scss:style.css
When you want to assign another value to the variable, make another file named "green.scss" like:
$color: green;
#import "style";
Then compile it with
sass green.scss:anotherstyle.css
It is bothering somewhat but enables to decide values of variables at compile time.