Reputation: 4661
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
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