Search code examples
csssassscss-mixins

Generate CSS classes dynamically based on variables - SCSS


I have color variables (example):


// _colors.scss
:root, * {
  --color-primary-50: 1,1,1;
  --color-primary-100: 2,2,2;
  --color-primary-200: 3,3,3;
}

And I want to generate classes based on the variables, for example:


// _background.scss
.bg-primary-50 {
  background: rgb(var(--color-primary-50));
}

.bg-primary-100 {
  background: rgb(var(--color-primary-100));
}

.bg-primary-200 {
  background: rgb(var(--color-primary-200));
}

I want to simplify my future modifications if I need to change or add new colors and dynamically populate my _background file with classes based on _colors variables.

It seems like a lot of monotonic work. Is there any way to get this result? Perhaps I should change my file structure?


Solution

  • use @each loop. Instead of creating the vars in :root add those in a single var (see below example)

    $colors : (
      "primary-50":  "1,1,1",
      "primary-100": "2,2,2",
      "primary-200": "3,3,3",
    );
    
    @each $color, $value in $colors {
        .bg-#{$color} {
            background-color: rgb($value);
        }
    }
    

    the above code compiled into

    .bg-primary-50 {
      background-color: #010101;
    }
    .bg-primary-100 {
      background-color: #020202;
    }
    .bg-primary-200 {
      background-color: #030303;
    }
    

    And for CSS --variables

    :root {
        @each $color, $value in $colors {
            --color-#{$color}: rgb($value);
        }
    }
    

    and 💥 you have CSS Variables

    :root {
      --color-primary-50: #010101;
      --color-primary-100: #020202;
      --color-primary-200: #030303;
    }
    

    Like you mentioned in your comment "will this solution work for the light and dark modes?" for that you can do something like this

    html[data-color-mode="dark"] {
      $dark-mode-colors: (
        "primary-color-50": "0, 0, 0",
        "primary-color-100": "1, 1, 1",
        "primary-color-200": "2, 2, 2",
      )
    
      @each $color, $value in $colors {
        .bg-#{$color} {
            background-color: $value;
        }
      }
    }
    
    // change your color scheme as you prefer method will remain the same
    html[data-color-mode="light"] {
      $light-mode-colors: (
        "primary-color-50": "0, 0, 0",
        "primary-color-100": "1, 1, 1",
        "primary-color-200": "2, 2, 2",
      )
    
      @each $color, $value in $colors {
        .bg-#{$color} {
            background-color: $value;
        }
      }
    }