Dear all I am developing a node app with vite and lit. I like to have the option that the user can change the style dynamically at runtime for instance to select between a dark and bright theme for the whole site.
I know that you can directly import
"css" files and apply it on single lit elements. But how I can change the style dynamically for the whole site? I also noticed that an ìmport from "xxxx.css"
can not contain a dynamic variable,so the following seems not to be supported?
let theme = "dark"
import "folder/" + theme + ".css";
Any suggestion how I can best achieve my goal?
This is best handled by setting all your colors in your elements as CSS Custom Properties. e.g.
class MyCustomCard extends LitElement {
static styles = css`
.card {
/* Set custom property and default value */
background-color: var(--sys-color-surface, #FFF);
color: var(--sys-color-on-surface, #000);
...
}
`;
...
}
Then you can have a theming.css file at the root of your document. e.g.
<!-- index.html -->
<head>
<link rel="stylesheet" href="theme.css">
</head>
/* theme.css */
/* light theme */
:root, body.force-light-mode {
--sys-color-surface: #FFF;
--sys-color-on-surface: #000;
...
}
/* auto dark theme */
@media (prefers-color-scheme: dark) {
:root {
--sys-color-surface: #000;
--sys-color-on-surface: #FFF;
...
}
}
/* user preference dark mode */
body.force-dark-mode {
/* This can be deduplicated with an @import https://developer.mozilla.org/en-US/docs/Web/CSS/@import */
--sys-color-surface: #000;
--sys-color-on-surface: #FFF;
...
}
Then you can have a dark theme toggle that toggles the force-*-mode
class on body:
class ThemeToggle extends LitElement {
render() {
return html`
<div>Select Theme</div>
<label>
Light Mode
<input
type="radio"
@change=${this.onChange('light')}
name="theme">
</label>
<label>
Follow System
<input
type="radio"
@change=${this.onChange('system')}
name="theme"
checked>
</label>
<label>
Dark Mode
<input
type="radio"
@change=${this.onChange('dark')}
name="theme">
</label>`
}
onChange = (mode) => (e) => {
if (e.target.checked) {
switch(mode) {
case 'light':
document.body.classList.add('force-light-mode');
break;
case 'dark':
document.body.classList.add('force-dark-mode');
break;
}
} else {
switch(mode) {
case 'light':
document.body.classList.remove('force-light-mode');
break;
case 'dark':
document.body.classList.remove('force-dark-mode');
break;
}
}
}
}