ShellZero
ShellZero

Reputation: 4661

Is there any way to append $ to a variable in sass?

I have around 196 images of country flags and each image is named after its two letter country code. I generated a sprite with all these images using gulp.spritesmith npm package. It also generates a css file (in my case, a scss file) to reference them in our project.

For simplicity, the following generated code is because of the two images.

/*generated code*/
$ad-name: 'ad';
$ad-x: 0px;
$ad-y: 14px;
$ad-offset-x: 0px;
$ad-offset-y: -14px;
$ad-width: 19px;
$ad-height: 14px;
$ad-total-width: 19px;
$ad-total-height: 1932px;
$ad-image: 'locate-sprite.png';
$ad: (0px, 14px, 0px, -14px, 19px, 14px, 19px, 1932px, 'locate-sprite.png',    'ad', );
$ae-name: 'ae';
$ae-x: 0px;
$ae-y: 966px;
$ae-offset-x: 0px;
$ae-offset-y: -966px;
$ae-width: 19px;
$ae-height: 14px;
$ae-total-width: 19px;
$ae-total-height: 1932px;
$ae-image: 'locate-sprite.png';
$ae: (0px, 966px, 0px, -966px, 19px, 14px, 19px, 1932px, 'locate-sprite.png', 'ae', );
$spritesheet-sprites: ($ad, $ae,);
$spritesheet: (19px, 1932px, 'locate-sprite.png', $spritesheet-sprites, );

@mixin sprite-width($sprite) {
  width: nth($sprite, 5);
}

@mixin sprite-height($sprite) {
  height: nth($sprite, 6);
}

@mixin sprite-position($sprite) {
  $sprite-offset-x: nth($sprite, 3);
  $sprite-offset-y: nth($sprite, 4);
  background-position: $sprite-offset-x  $sprite-offset-y;
}

@mixin sprite-image($sprite) {
  $sprite-image: nth($sprite, 9);
  background-image: url(#{$sprite-image});
}

@mixin sprite($sprite) {
  @include sprite-image($sprite);
  @include sprite-position($sprite);
  @include sprite-width($sprite);
  @include sprite-height($sprite);
}  

In my project, I created a mixin which overrides the above generated sprite mixin. That is as follows:

@mixin blah($sprite){
    &:before{
        display: inline-block;
        content: "\00a0";
        position: relative;
        vertical-align: middle;
        top: -2px;
        @include sprite-image($sprite);
        @include sprite-position($sprite);
        @include sprite-width($sprite);
        @include sprite-height($sprite);
    }
}

When I use this mixin in my project, I simply import the scss file generated and include this mixin. The following is the implementation:

@import "_gen.sprite";

$country-list: ad ae;
@each $current-country in $country-list {
  .imageflag-#{$current-country}{
       @include blah($ad); // This works
       @include blah($current-country); //This doesn't because, a string is passed instead of a variable. 
       margin-right: 10px;
}
}

But, In the above implementation, I want to pass the given list values (ad and ae) as variables (i.e., $ad and $ae) during the each loop.

You might say, why can't you just have the country list as following:

$country-list: $ad $ae;

I can't do this because, $ad and $ae values are already generated by the plugin in the scss file and are equivalent to a value which can't be passed into the mixin as it will throw an error again. Expecting a variable not a string.

So, I thought of using interpolation. So, I did the following:

$dollar: '$';
$country-list: ad ae;
@each $current-country in $country-list {
      .imageflag-#{$current-country}{
           @include blah(#{$dollar}#{$current-country}); //expected $ad and $ae but throws an error. 
           margin-right: 10px;
    }
    }

But the interpolation is not working on the dollar. I am unable to append dollar to a string variable.

So, is there any other way to interpolate or append a dollar symbol to a variable or a string to achieve the required output.

Any feedback or suggestions are greatly appreciated.

Thank you.

Upvotes: 1

Views: 2351

Answers (1)

ShellZero
ShellZero

Reputation: 4661

Firstly, the sprite mixin here doesn't accept strings. They accept variables. Hence, I tried to create a whole new list from the existing list by appending the $ to every list item. Even then, the end result was a string but not a variable.

After a while, I looked at the types of the variables generated with a simple amend. It was a string. And the variable which was passed to the mixin was a list. As there is only one single item in a string [Note: In SASS, a single string is implicitly a list], whenever I try to do a nth($country, 9), it throws an index out of bounds error.

So, final conclusion from that experiment is just to pass a list variable to the mixin.

Now, for every country list variable we pass to the mixin, there should be a specific class generated with it's properties. How do we do this? We need to loop through the list of lists.

Hence, I overwrote the mixin already generated by the spritesmith as follows:

@mixin sprites-loop($sprites) {
    @each $sprite in $sprites {
        $sprite-name: nth($sprite, 10);
        .iss-flag-#{$sprite-name} {
            @include sprite($sprite);
            margin-right: 5px;
        }
    }
}

Usage:

@include sprites-loop($spritesheet-sprites);

$spritesheet-sprites is a list of lists which is generated by the gulp.spritesmith in the css file.

By, simply using this one single line of @include, I didn't even had to iterate through the country list.

Coming to the interpolation, #{} is used to coerce the variables into strings. Even though when I using it thinking, an output would be a resemblance of the variable, it's still a string. Hence, the #{} doesn't work in this scenario.

Thanks a lot for everyone's comments and I hope this helps others who try to incorporate gulp.spritesmith in their projects.

Cheers,
SZ

Upvotes: 0

Related Questions