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?