4

I am trying to do theming for one of my projects and i was using css variables for the same. I was defining css variable as follows

.theme-1 {
    --var-1: #ffe;
    --var-2: #000;
}

.theme-2 {
    --var-1: #fff;
    --var-2: #000;
}

and in the html i was applying the theme as follows

<div [ngClass]="'theme-1'">
<!--content>

<-->
</div>

Everything works great except that css-variables are not supported till IE -11 as mentioned Here.

Question

Is there any way to achieve this with scss variables so that i can define global variables and change the value based on class .

Note: I am using angular for my project, hence i have to worry about view encapsulation as well. It would be great if the answer can be achieved with default encapsulation.

Thanks in advance.

Vikhyath Maiya
  • 3,122
  • 3
  • 34
  • 68

2 Answers2

6

I personally prefer using a function for that, but you could make it with a mixin too.

Create a Map with properties bind to as many values as themes you have.
Then, define a custom property for fetching this map and return the wanted value.

$theme: (
  color: (#000, #FFF),
  border: (dashed, solid),
  // etc.
);

@function theme($property, $index) {
  @return nth(map-get($theme, $property), $index);
}

.light.foo {
  color: theme(color, 1);
}

.dark.foo {
  color: theme(color, 2);
}

Demo SassMeister

Quentin Veron
  • 3,079
  • 1
  • 14
  • 32
  • Umm might work, but i have different files defining the theme variable. Using a function would require a static @theme variable with defined values which in my case wouldnt be possible as i have different files for themes. Any other elagent way of doing this ? – Vikhyath Maiya Oct 26 '18 at 17:35
4

Since SASS is compiled top-down, you may redefine the variables for each theme, and duplicate the common styles, which will be compiled to use the correct variable values.

_dark-theme.scss

// Variables for dark theme
$background-color: #333;
$color: #fff;

_light-theme.scss

// Variables for light theme
$background-color: #eee;
$text-color: #333;

_common-styles.scss

// Styles used across all themes, uses theme variables
body {
    background: $background-color;
    color: $text-color;
}

main.scss

.dark-theme {
    @import "dark-theme";
    @import "common-styles";
}

.light-theme {
    @import "light-theme";
    @import "common-styles";
}

Then use the desired theme class at the top level in your html.

<body class="dark-theme">
    ...
</body>
miir
  • 1,814
  • 1
  • 17
  • 25
  • There are multiple files with specific style definitions in it, for ex buttons.scss where i have t import the variables. At that time again the default value will be taken ! – Vikhyath Maiya Oct 29 '18 at 08:32
  • You could add a sass variable as a flag around the import statement in the buttons.scss or anywhere else where youa re importing the default variables. main.scss: `$skip-var-import: true;` -- buttons.scss: `@if not($skip-var-import) { @import 'default-variables'; }` – miir Oct 29 '18 at 20:04