Is there a way to make dynamic css variable color theming with scss?

22 Views Asked by At

I know the title may not be very intuitive.. So I've been developing a website for my music career using SCSS and an express server in typescript. I've came accross an issue: how can I make color themes and boutons themes while keeping the names simples and intuitive?

What I want to do: A btn-<style> class that has a specific style (example: a :before rectangle sliding under the button for a btn-primary style and a simple rectangle colored differently on a btn-secondary style) A color-<color> class that is used to make the button color themes (with both classes: <a href="#" class="btn-primary color-primary">Go there!</a>.

So multiple button styles with color theming and intuitive classes.

So as you may know, css has variables that allows this on client side:

/* Style one */
.btn-primary {
  --btn-color: #000;
  color: var(--btn-color);
  /* ... */
}

/* Style two */
.btn-secondary{
  --btn-color: #000;
  color: var(--btn-color);
  /* ... */
}

.color-primary {
  --btn-color: #bbb;
}

Which would be used as I want:

<a href="#" class="btn-primary color-primary">Hello!</a>

But scss cannot access those variables to (for example) darken when hovering, and manipulate colors. Here is how I make themes:

@each $color, $value in $theme-colors {
  .btn-color-#{$color} {
    /* Modify the colors here */
  }
}

And then the button primary style:

.btn-primary {
  background-color: var(--btn-bg); // And here I want to use that kind of mechanic
  color: var(--btn-color); // I am obviously not using css variables in scss like that, it's just an example on how I want to make this work
  border: $btn-border-width $btn-color solid;
  padding: $btn-padding;
  width: fit-content;
  line-height: $font-line-height-medium;
  position: relative;
  text-transform: uppercase;
  cursor: pointer;
  font-family: $btn-font;
  font-size: $font-normal;
  &:hover {
    background-color: darken(var(--btn-color), $btn-hover-percent);
    color: contrast-color(darken(var(--btn-color), $btn-hover-percent), $dark, $light);
    border-color: darken(var(--btn-color), $btn-hover-percent);
  }
  &:hover:before {
    transform: translateY(0) translateX(0);
    z-index: -1;
  }
  &:active {
    background-color: lighten(var(--btn-color), $btn-active-percent);
    color: contrast-color(lighten(var(--btn-color), $btn-active-percent), $dark, $light);
    border-color: lighten(var(--btn-color), $btn-active-percent);
    transform: scale(0.95);
  }
  &:active:before {
    transform: translateY(0) translateX(0);
    z-index: -1;
  }
  &:focus-visible {
    outline: $ring-width var(--btn-color) solid;
    outline-offset: $ring-offset;
    background-color: darken(var(--btn-color), $btn-hover-percent);
    color: contrast-color(darken(var(--btn-color), $btn-hover-percent), $dark, $light);
    border-color: darken(var(--btn-color), $btn-hover-percent);
  }
  &:focus-visible:before {
    transform: translateY(0) translateX(0);
    z-index: -1;
  }
  &:before {
    content: "";
    width: 100%;
    position: absolute;
    z-index: -1;
    top: 0;
    left: 0;
    height: 100%;
    transform: translateX($medium) translateY($medium);
    background-color: rgba(var(--btn-color), .5);
  }
  @include trans(background-color $timing-normal ease-in-out, border-color $timing-normal ease-in-out, color $timing-normal ease-in-out, box-shadow $timing-normal ease-in-out, transform $timing-normal ease-in-out);
}

All the color variables are defined in the file scss/_variables.scss following my project structure: static scss _core.scss

_variables.scss
_functions.scss
_fonts.scss
_mixins.scss
main.scss

css main.css (compiled from scss) ...

Any ideas ?How it looks for now

0

There are 0 best solutions below