DEV Community

Giulia Chiola
Giulia Chiola

Posted on • Originally published at giuliachiola.dev

Create CSS classes dynamically

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>
Enter fullscreen mode Exit fullscreen mode

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);
}

Enter fullscreen mode Exit fullscreen mode

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});
  }
}
Enter fullscreen mode Exit fullscreen mode

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-"
Enter fullscreen mode Exit fullscreen mode

Read more about sass interpolation

The workaround

  • create a mixin using 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);
  }
}
Enter fullscreen mode Exit fullscreen mode
  • use the tag list to dynamically generate classes names
$tags: git, vsc, nodejs;

@each $tag in $tags {
  .c-card--#{$tag} {
    @include card-gradient($tag);
  }
}
Enter fullscreen mode Exit fullscreen mode

🖥 Codepen example

Dynamic classes using CSS vars

Note that if we use CSS vars instead of SASS vars we can interpolate the class name with #{} syntax.

  1. Declare the CSS var
:root {
  --co_palette-1: #ef476f;
  /* ... */
}
Enter fullscreen mode Exit fullscreen mode
  1. Use the interpolation where it is called, for example in a @for loop
@for $i from 1 through 5 {
  .t-palette-color--#{$i} {
    background-color: var(--co_palette-#{$i});
  }
}
Enter fullscreen mode Exit fullscreen mode

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%)};
}
Enter fullscreen mode Exit fullscreen mode
@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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)