Sass variable interpolation with backslash in output
Asked Answered
S

6

12

I'm creating some icon font rules for using in my site. Using Sass I wanted to list all the icons in a list variable and use @each to loop through them all.

Code looks like this:

$icons: 
    wifi 600,
    wifi-hotspot 601,
    weather 602;

@each $icon in $icons {
    .icon-#{nth($icon, 1)}, 
    %icon-#{nth($icon, 1)} {
        content: "\#{nth($icon, 2)}";
    }
}

The problem is the backslash on the content: line. I need it for the character encoding, but it escapes the variable interpolation, outputting CSS that looks like this:

.icon-wifi {
  content: "\#{nth($icon, 2)}";
}

Adding one more backslash like this: content: "\\#{nth($icon, 2)}"; outputs this CSS:

.icon-wifi {
  content: "\\600";
}

Is there a way to get the Sass to output CSS with only a single backslash while keeping the variable interpolation?

Spall answered 6/2, 2014 at 16:40 Comment(2)
In Sass 3.4.13, try this solution on there: #26112482Briannabrianne
I believe this is related to this issue: github.com/sass/libsass/issues/1115Boustrophedon
C
3

You can add the backslash to the parameter in the $icons variable. That is,

$icons: wifi "\600", wifi-hotspot "\601", weather "\602";

@each $icon in $icons {
  .icon-#{nth($icon, 1)}, %icon-#{nth($icon, 1)} {
    content: "#{nth($icon, 2)}";
  }
}

Generated CSS:

.icon-wifi {
  content: "\600"; 
}

.icon-wifi-hotspot {
  content: "\601"; 
}

.icon-weather {
  content: "\602"; 
}   
Covariance answered 6/2, 2014 at 16:56 Comment(9)
Thanks! That worked. But I do wonder if there is a character sequence or function that would allow the backslash to be outside the $icons variable.Spall
@Spall Do you actually need to have the backslash separate?Heterogeneous
@Heterogeneous No, the answer provided a solution to my problem. I'm just wondering regarding the technical aspect. Is there a way to output a backslash immediately before and interpolated sass variable?Spall
@Spall I did tinker with it a bit (including having the backslash be a variable), but I couldn't get the desired output. I suspect it might be a bug in Sass.Heterogeneous
@Spall in Sass 3.3 it's possible to overcome this problem with slicing the backslash from a string, and then combining it with any code like so str-slice("\x",1,1) + $code. See my answer here: #21642333Addlebrained
@MartinTurjak Thanks man, that works (indirect as it may be).Spall
Darn, doesn't look like this works anymore. I'm getting generated CSS with strange characters instead of backslashes.Costello
@SeanAdkinson Did you ever come up with a solution to the "strange characters" being added?Weapon
@Jake I don't recall finding a fix, no. I think we just came up with an entirely different solution, but it was too long ago to remember for sure.Costello
C
12

I got this to work by messing with the interpolation

sassmesiter demo

// ----
// Sass (v3.4.21)
// Compass (v1.0.3)
// ----

$icons: 
    wifi 600,
    wifi-hotspot 601,
    weather 602;

@each $icon in $icons {
    .icon-#{nth($icon, 1)}, 
    %icon-#{nth($icon, 1)} {
        content: #{'"\\' + nth($icon, 2) + '"'}; // <------ See this line
    }
}

compiles to

.icon-wifi {
  content: "\600";
}

.icon-wifi-hotspot {
  content: "\601";
}

.icon-weather {
  content: "\602";
}
Cambist answered 27/7, 2017 at 4:24 Comment(2)
Best solution for me !Nightrider
This worked for me well :) content: #{'"\\' + $unicode + '"'}Jessee
C
7

If you include the backslash in the actual variable, then when the sass generates the css, it will actually generate the calculated unicode character instead of outputting the unicode in the css output. This still usually works but it's hard to debug if something is going wrong and it is a bit more prone to cause issues in the browser in rendering the icon.

To output the actual unicode in the generated CSS, you can do this:

@function icon($character){
    @return unquote('\"') + unquote(str-insert($character,'\\', 1)) + unquote('\"');
}

$icon-thing: "e60f";

.icon-thing:before {
    content: icon($icon-thing); //outputs content: "\e60f";
}
Celandine answered 7/3, 2016 at 0:52 Comment(1)
There's an extra closing bracket in your functionControversial
C
3

You can add the backslash to the parameter in the $icons variable. That is,

$icons: wifi "\600", wifi-hotspot "\601", weather "\602";

@each $icon in $icons {
  .icon-#{nth($icon, 1)}, %icon-#{nth($icon, 1)} {
    content: "#{nth($icon, 2)}";
  }
}

Generated CSS:

.icon-wifi {
  content: "\600"; 
}

.icon-wifi-hotspot {
  content: "\601"; 
}

.icon-weather {
  content: "\602"; 
}   
Covariance answered 6/2, 2014 at 16:56 Comment(9)
Thanks! That worked. But I do wonder if there is a character sequence or function that would allow the backslash to be outside the $icons variable.Spall
@Spall Do you actually need to have the backslash separate?Heterogeneous
@Heterogeneous No, the answer provided a solution to my problem. I'm just wondering regarding the technical aspect. Is there a way to output a backslash immediately before and interpolated sass variable?Spall
@Spall I did tinker with it a bit (including having the backslash be a variable), but I couldn't get the desired output. I suspect it might be a bug in Sass.Heterogeneous
@Spall in Sass 3.3 it's possible to overcome this problem with slicing the backslash from a string, and then combining it with any code like so str-slice("\x",1,1) + $code. See my answer here: #21642333Addlebrained
@MartinTurjak Thanks man, that works (indirect as it may be).Spall
Darn, doesn't look like this works anymore. I'm getting generated CSS with strange characters instead of backslashes.Costello
@SeanAdkinson Did you ever come up with a solution to the "strange characters" being added?Weapon
@Jake I don't recall finding a fix, no. I think we just came up with an entirely different solution, but it was too long ago to remember for sure.Costello
C
1

Use unquote and double slash

$var:123 → content:"\e123"

 content:#{unquote('\"')+("\\")+("e")+$var+unquote('\"')};
Cod answered 14/1, 2020 at 20:18 Comment(0)
C
0

If you are using Gulp to compile your Sass files, installing this Gulp plugin is probably the easiest way to get around the issue:

https://www.npmjs.com/package/gulp-sass-unicode

var sass = require('gulp-sass');
var sassUnicode = require('gulp-sass-unicode');

gulp.task('sass', function(){
  gulp.src('style.scss')
    .pipe(sass())
    .pipe(sassUnicode()) // <-- This is the bit that does the magic
    .pipe(gulp.dest( "css/" ));
});

There is no need to make any code alterations in your Sass files. Write out your Sass code how you want and the unicode characters are decoded back into regular escaped strings in the output CSS automatically.

Input SCSS

$testContent: "\f26e";

#test {
  content:  $testContent;
}

Output CSS

#test {
  content: "\f26e";
}
Celandine answered 6/10, 2018 at 4:13 Comment(0)
R
0

Unfortunately, these solutions were not entirely working for me but I was finally able to get it working with SASS maps

//node-sass 4.11.0
//libsass 3.5.4

$hexes: (
           checkmark: \2714
        );

@function out-content($var) {
    @return unquote("\"#{ $var }\""); 
}

@each $mod, $code in $hexes {    
    .#{$mod}-after {
        &:after {
            content: out-content($code);
        }
    }
}

//output
//.checkmark-after:after {
    //content: "\2714";
//}
Ricoriki answered 7/2, 2019 at 19:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.