Sass store selector in variable - css

I am trying to save a selector in SASS for easier referencing later, however I get a syntax error.
Here's what I'm trying to do:
$icon: [class*="icon"];

You need to convert it to a string if you want to use it as a variable:
$icon: '[class*="icon"]';
#{$icon} {
// stuff
}

Related

The #use feature of Sass

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.

CSS variables and SASS functions

We know the advantages of using CSS4 variables but what if we need to get these values from a SASS function like so?:
:root {
--gap-l: toRem(10);
}
toRem is a Sass function that I call to get the sizes dynamically:
$fontSize: 16;
#function toRem($val) {
#return $val / $fontSize * 1.6 + 0rem;
}
This won't fail but won't work either. To have this working we can just have the value directly on --gap-l or keep using SASS vars.
If I try something like --gap-l: #{toRem(10)}; this is the error I get:
It doesn't call the SASS function
You can definitely do that: what you're missing is simply using string interpolation, i.e.:
:root {
--gap-l: #{toRem(10)};
}
The reason is highlighted in their "breaking changes" documentation with regards to CSS variables:
To provide maximum compatibility with plain CSS, more recent versions of Sass require SassScript expressions in custom property values to be written within interpolation. Interpolation will also work for older Sass versions, and so is recommended for all stylesheets.
Try this --gap-l: #{toRem(10)};, the #{} syntax is called interpolation. In the experience of heading bugs myself, when you want to use a SASS expression's raw value along with normal CSS, if you can't use the concise syntax like just toRem(10), try adding interpolation to see if it works.
Another example:
$padding: 5px;
.element {
width: calc(100% - $padding); // will not work, it must be:
width: calc(100% - #{$padding});
}
Here is the code with the updated question: https://jsfiddle.net/bcw763en/.
Notice that if you put :root above the #function, it'll not work.

Set CSS for dynamic element CoffeeScript

I am trying to write a code that set CSS for some dynamic elements added on click on a link.
As per the example code in CoffeeScript tutorial it should be working with the following code.
temp = temp+1
$ '.box_'+temp
.css 'background', 'white'
Here temp is a variable integer.
I tried with static values like
$ '.box_1'
.css 'background', 'white'
but it returns something like this with .css not a function error
$('.box_1'.css('left', 100));
Just add parens to remove ambiguity and save yourself the headache.
temp = temp+1
$('.box_'+temp)
.css('background', 'white')
Sexy function calls are optional syntactic sugar, not required. You should not be using language features if doing so makes your code less clear for humans or machines (or in this case, both!)

How can I create unique variables when using mixins as functions in LESS?

I needed to create a function for some big color work on my Bootstrap variables. Unfortunately LESS doesn't allow you to create functions that can be called like theirs (ex. #myvar: darken(#color, 20%);).
The option provided on the doc site is to use a mixin that returns a variable. This worked well for me when I used it where the variable was declared as the property value, but I need to run my new mixin on many variables in the Bootstrap variable.less file. If I call the mixin multiple times there, it always returns the first color.
Part that works:
.mixin(#color) {
#var: #color;
}
.caller-1 {
.mixin(blue);
color:#var;
}
.caller-2 {
.mixin(red);
color:#var;
}
CSS
.caller-1 {
color:blue;
}
.caller-2 {
color:red;
}
What does not work:
.mixin(blue);
#color-1: #var; // My value is now blue
.mixin(red);
#color-2: #var; // My value is also blue
I thought I could get around this by building a unique variable in the mixin, but I can't find anyway to build one.
.mixin(#color; #num)
#var+#{num}: #color;
}
.mixin(blue; 1);
#color-1: #var1;
.mixin(red; 2);
#color-2: #var2;
Any idea on how to create a variable name in a mixin or other ideas on how to make one work like the LESS functions?
You can't define variables dynamically in LESS right now, but you can dynamically define selectors (as you probably knew). I will just give an example of that and leave it to you to apply it to the color/variables issue.
.towerMaker (#index) when (#index > 0) {
.block-#{index} {
z-index: #{index};
}
.towerMaker(#index - 1);
}
.towerMaker (7);
Variables are actually constants, and their scope is based only on context (where they appear in the block doesn't matter). It's only different when you call it within a selector block because of context. When you call the mixin at top-level, you define #var once for that level and it won't be overriden.
If you have to use variables, I suggest you try to find a solution taking advantage of the context. For example, you might be able to try something with mixin guards & when(condition) {...} (it's actually even simpler, as #seven-phases-max commented below). This is a way to run a mixin outside the context of a selector but still inside a context (updated example):
& {
.mixin(red);
.test1 { color: #var; }
}
& {
.mixin(blue);
.test1 { color: #var; }
}
You actually can define functions that will be called using Less by your Less runtime, but they can't be defined using Less. This is possible if you run your processor using Node.js, for example. But it's quite a hack and not trivial since you have to write them in JavaScript and wrap values in undocumented less.js types.
You can also call core JavaScript enclosing it within backticks (this is also undocumented). It's good for small blocks of code and for core functions:
length: unit(`Math.log(#{value})`, px);
If you run your Less processor from a Node.js app you can call your own functions that way.

SASS: Set variable at compile time

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.

Resources