In this minimal sass example I try to concatenate a string and a string generated by inspect()
// Can not be changed:
#function get-filename() {
$filename: inspect("foo.jpg");
#return $filename;
}
// My code:
$url: "path/" + get-filename();
body {
background-image: url($url);
}
However this doesn't resolve as required, because there are quotes around foo.jpg
body {
background-image: url('path/"foo.jpg"');
}
Can you tell me how to correct my code such that the resolving css is:
body {
background-image: url('path/foo.jpg');
}
As stated in the comment, in my application I cannot change the function that generates $filename.
I though that this could be solved with $url: "path/" + unquote(get-filename()); but this doesn't seem to help.
unquote should work here but that looks to be a bug in Sass itself when combining it with the result of inspect.
You could potentially use a function to drop the first and last character in the string:
// Can not be changed:
#function get-filename() {
$filename: inspect("foo.jpg");
#return $filename;
}
#function dropOuterCharacters($input) {
#return str-slice($input, 2, str-length($input) - 1);
}
$url: "path/" + dropOuterCharacters(get-filename());
body {
background-image: url($url);
}
Related
I'm writing some sass to generate a set of icons based on a series of parameters. I have a function that analyses a set of variables and then returns a 'scenario' variable which in turn is used to filter the information taken from the nested map where everything is stored.
The code which retreives the information from the nested map is as follows:
#each $key-lv0, $lv0 in $icon-config {
#if($key-lv0 == $scenario) {
.icon{
#each $key-lv1, $lv1 in $lv0 {
#if type-of($lv1) != "map" {
#{$key-lv1}: $lv1;
}
#each $key-lv2, $lv2 in $lv1 {
#if type-of($lv2) != "map" {
.#{$key-lv1} {
#{$key-lv2}: $lv2;
}
}
#each $key-lv3, $lv3 in $lv2 {
#if($key-lv2 == "hover") {
.#{$key-lv1}:#{$key-lv2} {
#{$key-lv3}: $lv3;
}
} #else {
.#{$key-lv1} #{$key-lv2} {
#{$key-lv3}: $lv3;
}
}
}
}
}
}
}
}
... and this produces something along these lines:
.icon .icon-header {
background-color: #00a9f0;
}
.icon .icon-header:hover {
border-color: #040100;
}
... etc ...
... which is fine - repeated statements aside whicvh I'll deal with later.
The problem is the cap between ".icon" and ".icon-header". These classes will all be used in a single element and for the css to be interpretted correctly it needs to generate something like this:
.icon.icon-header {
background-color: #00a9f0;
}
.icon.icon-header:hover {
border-color: #040100;
}
I've tried bringing ".icon" down like so:
#if type-of($lv1) != "map" {
.icon#{$key-lv1}: $lv1;
}
and removing it from the top but sass rejects this with the following error:
Error: Properties are only allowed within rules, directives, mixin includes, or other properties.
It seems such a minor thing but it's nagging me and I can't seem to find an answer.
I want to check if the value provides to a function is a map or not.
#function func($props...) {
#if(is-map($props)) {
#return 'something';
}
#else {}
}
h1 {
color: func((color: red));
}
I'm getting the error:
(color: red) isn't a valid CSS value.
What am I doing wrong?
I personally never heard about any native Sass function called is-map. If you want to check the type of something, use the type-of function, so for example, checking for type-of($props) == map would solve your problem in this case.
#function func($props...) {
#if(type-of($props) == map) {
#return 'something';
}
#else {}
}
Because function returns map. Not a color as expected. Use map-get to get the access to properties values.
#return map-get($props, color);
And you have the variable argument. To get the first of arguments use nth($props, 1).
Sassmeister demo.
Update
If parameters in map are dynamic you can use this mixin instead of function.
#mixin print($declarations) {
#if $declarations {
#each $property, $value in $declarations {
#{$property}: $value
}
} #else {
#error "mixin print: $declarations is not specified";
}
}
Mixin sassmeister demo.
I'm trying to use an each loop in Sass but the css is compiling with the variable name instead of the content of the variable.
$green-1: #9ae200;
$green-2: #5ea600;
$color-list: green-1 green-2;
#each $single-color in $color-list {
&.#{$single-color} {
background-color: $single-color;
}
}
The output I am looking for is:
.green-1 {
background-color:#9ae200;
}
.green-2 {
background-color:#5ea600;
}
But the css is compiling as:
.green-1 {
background-color:green-1;
}
.green-2 {
background-color:green-2;
}
So to try to get the dollar sign in there I tried this:
#each $single-color in $color-list {
#function create-variable($variable){
#return "$" + $variable;
}
&.#{$single-color} {
background-color: create-variable($single-color);
}
}
But that compiled as:
.green-1 {
background-color:$green-1;
}
.green-2 {
background-color:$green-2;
}
Sass is not reading the variables for some reason and is taking them literally. Anyone know how to make this work?
You cannot create dynamic variable in sass. Instead you can achieve your desired result using map
example:
$green-1: #9ae200;
$green-2: #5ea600;
$color-map: (
green-1: $green-1,
green-2: $green-2,
);
.body{
#each $key,$value in $color-map {
&.#{$key} {
background-color: $value;
}
}
}
How do I return a hex code using the SASS lighten function?
#function returnHexValue($color){
#debug $color;
#if $color == "white" {
#return "#fff";
}
#if $color == "black" {
#return "#000";
}
#return $color;
}
When I use something like returnHexValue(lighten(#000,100%));, I still get the value returned as white instead of #fff.
You can use following function that will force Hex value
#function force-hex($color) {
#if type-of($color) == 'color' {
$hex: str-slice(ie-hex-str($color), 4);
#return unquote("\##{$hex}");
}
#return $color;
}
body{
color: force-hex(lighten(#000,100%));
}
Already there are few request in SASS github project to prevent conversion of Hex to a color value. You can follow below issues
https://github.com/sass/sass/issues/343
https://github.com/sass/sass/issues/363
I created the map with colors and their modifications (light, dark etc) and custom function for getting values from this map.
$colors: (
text: #383838,
cyan: (
base: #54c2e3,
light: lighten(#54c2e3, 15%),
dark: darken(#54c2e3, 15%)
)
)
#function color($color-name, $color-variant:null) {
#if $color-variant != null {
#return map-get(map-get($colors,$color-name),$color-variant);
} #else {
#if type-of(map-get($colors,$color-name)) == 'map' {
#return map-get($colors,'base');
} #else {
#return map-get($colors,$color-name);
}
}
}
But when i put this function inside rgba:
background: rgba(color(cyan), .5);
i get an error
Error: argument `$color` of `rgba($color, $alpha)` must be a color
Is there any possible way to use functions as parameters inside sass rgba function?
Maybe i'm blind, but i couldn't google an answer.
Based on my understanding, the problem was with the value returned by the custom function.
The below line of code within the #if part of the #else condition would actually not return anything based on your settings. You should first get the color's map based on the value passed as argument and then pick the base color value from that map.
#return map-get($colors,base);
So, the correct #return statement should have been like in the below code block.
#function color($color-name, $color-variant:null) {
#if $color-variant != null {
#return map-get(map-get($colors,$color-name),$color-variant);
} #else {
#if type-of(map-get($colors,$color-name)) == 'map' {
#return map-get(map-get($colors,$color-name),base); /* your problem was here */
} #else {
#return map-get($colors,$color-name);
}
}
}
CodePen Demo (the a tag's color and background are set using the output of the function).