SASS interpolation is an useful tool that comes in handy when we have to create CSS classes name dynamically from an array.
For the first version of this blog, I wanted different gradients based on post tag (git, vsc, nodejs...). Each tag is append to the main card class in order to create a modifier
// card.njk
<article class="c-card c-card--{{ tag }}"> ... </div>
and its CSS was this
// card.scss
$co_card-gradient-git: #eb3349, #f45c43;
$co_card-gradient-vsc: #1a2980, #26d0ce;
$co_card-gradient-nodejs: #36582f, #7ab659;
.c-card--git {
  background: linear-gradient(to right, $co_card-gradient-git);
}
.c-card--vsc {
  background: linear-gradient(to right, $co_card-gradient-vsc);
}
.c-card--nodejs {
  background: linear-gradient(to right, $co_card-gradient-nodejs);
}
In attempt to remove repetitions and have a DRY (Don't Repeat Yourself) code, I tried to loop through a SASS list and generate classes
$tags: git, vsc, nodejs;
@each $tag in $tags {
  .c-card--#{$tag} {
    background: linear-gradient(to right, $co_card-gradient-#{tag});
  }
}
but unfortunately SASS does not support variable name interpolation at the moment! 💔
If you try to compile the snippet above, you will get
Sass Error: Undefined variable: "$co_card-gradient-"
Read more about sass interpolation
The workaround
- create a mixinusing SASS conditionals with all cases you need
@mixin card-gradient($tag) {
  @if $tag == 'git' {
    background: linear-gradient($co_card-gradient-git);
  }
  @else if $tag == 'vsc' {
    background: linear-gradient($co_card-gradient-vsc);
  }
  @else if $tag == 'nodejs' {
    background: linear-gradient($co_card-gradient-nodejs);
  }
}
- use the tag list to dynamically generate classes names
$tags: git, vsc, nodejs;
@each $tag in $tags {
  .c-card--#{$tag} {
    @include card-gradient($tag);
  }
}
Dynamic classes using CSS vars
Note that if we use CSS vars instead of SASS vars we can interpolate the class name with #{} syntax.
- Declare the CSS var
:root {
  --co_palette-1: #ef476f;
  /* ... */
}
- Use the interpolation where it is called, for example in a @forloop
@for $i from 1 through 5 {
  .t-palette-color--#{$i} {
    background-color: var(--co_palette-#{$i});
  }
}
If we need to mantain SASS vars (in my code, I needed to use darken and lighten SASS function) we could interpolate classes name like this:
$co_palette-1: #ef476f;
$co_palette-2: #ffc233;
$co_palette-3: #06d6a0;
$co_palette-4: #1b98e0;
$co_palette-5: #ff9f1c;
:root {
  --co_palette-1: #{$co_palette-1};
  --co_palette-2: #{$co_palette-2};
  --co_palette-3: #{$co_palette-3};
  --co_palette-4: #{$co_palette-4};
  --co_palette-5: #{$co_palette-5};
  --co_palette-1--lighten: #{lighten($co_palette-1, 10%)};
  --co_palette-2--lighten: #{lighten($co_palette-2, 10%)};
  --co_palette-3--lighten: #{lighten($co_palette-3, 10%)};
  --co_palette-4--lighten: #{lighten($co_palette-4, 10%)};
  --co_palette-5--lighten: #{lighten($co_palette-5, 10%)};
}
@for $i from 1 through 5 {
  .t-palette-color--#{$i} .c-card::before {
    background-color: var(--co_palette-#{$i});
    color: var(--co_palette-#{$i}--lighten);
  }
}
Output:
.t-palette-color--1 .c-card::before {
  background-color: var(--co_palette-1);
  color: var(--co_palette-1--lighten);
}
.t-palette-color--2 .c-card::before {
  background-color: var(--co_palette-2);
  color: var(--co_palette-2--lighten);
}
.t-palette-color--3 .c-card::before {
  background-color: var(--co_palette-3);
  color: var(--co_palette-3--lighten);
}
.t-palette-color--4 .c-card::before {
  background-color: var(--co_palette-4);
  color: var(--co_palette-4--lighten);
}
.t-palette-color--5 .c-card::before {
  background-color: var(--co_palette-5);
  color: var(--co_palette-5--lighten);
}
 

 
    
Top comments (0)