I\'m trying to use string interpolation on my variable to reference another variable:
// Set up variable and mixin
$
Sass does not allow variables to be created or accessed dynamically. However, you can use lists for similar behavior.
scss:
$list: 20px 30px 40px;
@mixin get-from-list($index) {
width: nth($list, $index);
}
$item-number: 2;
#smth {
@include get-from-list($item-number);
}
css generated:
#smth {
width: 30px;
}
This is actually possible to do using SASS maps instead of variables. Here is a quick example:
Referencing dynamically:
$colors: (
blue: #007dc6,
blue-hover: #3da1e0
);
@mixin colorSet($colorName) {
color: map-get($colors, $colorName);
&:hover {
color: map-get($colors, $colorName#{-hover});
}
}
a {
@include colorSet(blue);
}
Outputs as:
a { color:#007dc6 }
a:hover { color:#3da1e0 }
Creating dynamically:
@function addColorSet($colorName, $colorValue, $colorHoverValue: null) {
$colorHoverValue: if($colorHoverValue == null, darken( $colorValue, 10% ), $colorHoverValue);
$colors: map-merge($colors, (
$colorName: $colorValue,
$colorName#{-hover}: $colorHoverValue
));
@return $colors;
}
@each $color in blue, red {
@if not map-has-key($colors, $color) {
$colors: addColorSet($color, $color);
}
a {
&.#{$color} { @include colorSet($color); }
}
}
Outputs as:
a.blue { color: #007dc6; }
a.blue:hover { color: #3da1e0; }
a.red { color: red; }
a.red:hover { color: #cc0000; }
I came across the need to reference a colour dynamically recently.
I have a _colours.scss file for every project, where I define all my colours once and reference them as variables throughout.
In my _forms.scss file I wanted to setup button styles for each colour available. Usually a tedious task. This helped me to avoid having to write the same code for each different colour.
The only downside is that you have to list each colour name and value prior to writing the actual css.
// $red, $blue - variables defined in _colours.scss
$colours:
'red' $red,
'blue' $blue;
@each $name, $colour in $colours {
.button.has-#{$name}-background-color:hover {
background-color: lighten($colour, 15%);
}
}
To make a dynamic variable is not possible in SASS as of now, since you will be adding/connecting another var that needs to be parsed once when you run the sass command.
As soon as the command runs, it will throw an error for Invalid CSS, since all your declared variables will follow hoisting.
Once run, you can't declare variables again on the fly
To know that I have understood this, kindly state if the following is correct:
you want to declare variables where the next part (word) is dynamic
something like
$list: 100 200 300;
@each $n in $list {
$font-$n: normal $n 12px/1 Arial;
}
// should result in something like
$font-100: normal 100 12px/1 Arial;
$font-200: normal 200 12px/1 Arial;
$font-300: normal 300 12px/1 Arial;
// So that we can use it as follows when needed
.span {
font: $font-200;
p {
font: $font-100
}
}
If this is what you want, I am afraid as of now, this is not allowed
Here's another option if you're working with rails, and possibly under other circumstances.
If you add .erb to the end of the file extension, Rails will process erb on the file before sending it to the SASS interpreter. This gives you a can chance to do what you want in Ruby.
For example: (File: foo.css.scss.erb)
// Set up variable and mixin
$foo-baz: 20px; // variable
<%
def do_this(bar)
"width: $foo-#{bar};"
end
%>
#target {
<%= do_this('baz') %>
}
Results in the following scss:
// Set up variable and mixin
$foo-baz: 20px; // variable
#target {
width: $foo-baz;
}
Which, of coarse, results in the following css:
#target {
width: 20px;
}
Anytime I need to use a conditional value, I lean on functions. Here's a simple example.
$foo: 2em;
$bar: 1.5em;
@function foo-or-bar($value) {
@if $value == "foo" {
@return $foo;
}
@else {
@return $bar;
}
}
@mixin do-this($thing) {
width: foo-or-bar($thing);
}