How to use CSS variables in SCSS?

1.3k views Asked by At

I use SCSS code in my Laravel 8 project with webpack. I want to handle switching dark mode and light mode and manually overwrite the browser settings too.

I search a while to find solution for this problem, and I checked this question and many more, tried out, but found not working solutions only.

Here is my SCSS code:

// colors in light mode
$color-primary: hsl(19, 8%, 52%);
$color-primary-hover: hsl(17, 8%, 45%);

// colors in dark mode
$color-dark-primary: hsl(18, 27%, 52%);
$color-dark-primary-hover: hsl(17, 8%, 57%);

@media (prefers-color-scheme: light) {
    :root {
        --color-primary: #{$color-primary};
        --color-primary-hover: #{$color-primary-hover};
    }
}

@media (prefers-color-scheme: dark) {
    :root {
        --color-primary: #{$color-dark-primary};
        --color-primary-hover: #{$color-dark-primary-hover};
    }
}

// overwrite light mode
@media (prefers-color-scheme: light) {
    body.forceDarkMode {
        --color-primary: #{$color-dark-primary};
        --color-primary-hover: #{$color-dark-primary-hover};
    }
}


.btn-primary {
    background-color: color(primary);

    &:hover {
        background-color: color(primary-hover);
    }
}

As the upper linked StackOverflow answer suggested I implemented this code:

@function color($color-name) {
    @return var(--color-#{$color-name});
}

And the compiled result is this:

.btn-primary {
  background-color: undefined;
}
@media (prefers-color-scheme: dark){
  .btn-primary{
    background-color: #a67764;
  }
}
@media (prefers-color-scheme: light){
  .btn-primary{
    background-color: #8e817b;
  }
}

.btn-primary:hover {
  background-color: undefined;
}
@media (prefers-color-scheme: dark){
  .btn-primary:hover{
    background-color: #9a8e89;
  }
}
@media (prefers-color-scheme: light){
  .btn-primary:hover{
    background-color: #7c6f6a;
  }
}

Of course on the body element I toggle forceDarkMode class name with JavaScript when user change a checkbox.

Now I think the undefined value is shomehow related to my basic problem: I expect something like this code:

.btn-primary {
  background-color: var(--color-primary);
}
@media (prefers-color-scheme: dark){
  .btn-primary{
    background-color: var(--color-primary);
  }
}
@media (prefers-color-scheme: light){
  .btn-primary{
    background-color: var(--color-primary);
  }
}

But the sass compiler change the CSS variables (more precisely the var(--css-variable-name) string) to SCSS variable's value.

UPDATE:

Here is the webpack.mix.js file's content:

const mix = require('laravel-mix');
const fs = require('fs');
const webpack = require('webpack');

require('dotenv').config();

const domain = process.env.APP_URL.replace(/https?:\/\//, '');
const mixPath = 'theme_' + domain.replace(/\./g, '_');

if (mix.inProduction()) {
  mix.version();
}

mix.js('resources/themes/' + domain + '/js/app.js', 'public/' + mixPath + '/js')
  .vue()
  .sass('resources/themes/' + domain + '/css/app.scss', 'public/' + mixPath + '/css')
  .options({
    postCss: [
      require('postcss-css-variables')()
    ]
  })
  .copyDirectory('resources/themes/' + domain + '/img/', 'public/' + mixPath + '/img');

mix.webpackConfig({
  plugins: [
    new webpack.DefinePlugin({
      __VUE_OPTIONS_API__: true,
      __VUE_PROD_DEVTOOLS__: false,
    }),
  ],
});

How can I avoid this replace and keep the CSS variables in the code?

0

There are 0 answers