如何使用Vite和Lit动态更改整个站点的CSS?

huangapple go评论112阅读模式
英文:

How to change CSS dynamically for whole site with vite and lit?

问题

Dear all, 我正在开发一个使用 Vite 和 Lit 的 Node 应用程序。我希望用户可以在运行时动态更改样式,例如在整个站点之间选择暗黑和明亮的主题。

我知道您可以直接import“css”文件并将其应用于单个 Lit 元素。但是如何在整个站点上动态更改样式呢?我还注意到ìmport from "xxxx.css"不能包含动态变量,因此以下内容似乎不受支持?

  1. let theme = "dark"
  2. import "folder/" + theme + ".css";

有什么建议可以帮助我实现这个目标吗?

英文:

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?

  1. let theme = "dark"
  2. import "folder/" + theme + ".css";

Any suggestion how I can best achieve my goal?

答案1

得分: 1

这最好通过将所有元素中的颜色设置为CSS自定义属性来处理。例如:

  1. class MyCustomCard extends LitElement {
  2. static styles = css`
  3. .card {
  4. /* 设置自定义属性和默认值 */
  5. background-color: var(--sys-color-surface, #FFF);
  6. color: var(--sys-color-on-surface, #000);
  7. ...
  8. }
  9. `;
  10. ...
  11. }

然后,您可以在文档的根目录下创建一个名为theme.css的主题文件。例如:

  1. <!-- index.html -->
  2. <head>
  3. <link rel="stylesheet" href="theme.css">
  4. </head>
  1. /* theme.css */
  2. /* 亮色主题 */
  3. :root, body.force-light-mode {
  4. --sys-color-surface: #FFF;
  5. --sys-color-on-surface: #000;
  6. ...
  7. }
  8. /* 自动暗色主题 */
  9. @media (prefers-color-scheme: dark) {
  10. :root {
  11. --sys-color-surface: #000;
  12. --sys-color-on-surface: #FFF;
  13. ...
  14. }
  15. }
  16. /* 用户偏好的暗色模式 */
  17. body.force-dark-mode {
  18. /* 这可以使用 @import 来去重复 https://developer.mozilla.org/en-US/docs/Web/CSS/@import */
  19. --sys-color-surface: #000;
  20. --sys-color-on-surface: #FFF;
  21. ...
  22. }

然后,您可以创建一个切换暗色主题的切换按钮,该按钮会在body上切换force-*-mode类:

  1. class ThemeToggle extends LitElement {
  2. render() {
  3. return html`
  4. <div>Select Theme</div>
  5. <label>
  6. Light Mode
  7. <input
  8. type="radio"
  9. @change=${this.onChange('light')}
  10. name="theme">
  11. </label>
  12. <label>
  13. Follow System
  14. <input
  15. type="radio"
  16. @change=${this.onChange('system')}
  17. name="theme"
  18. checked>
  19. </label>
  20. <label>
  21. Dark Mode
  22. <input
  23. type="radio"
  24. @change=${this.onChange('dark')}
  25. name="theme">
  26. </label>`
  27. }
  28. onChange = (mode) => (e) => {
  29. if (e.target.checked) {
  30. switch(mode) {
  31. case 'light':
  32. document.body.classList.add('force-light-mode');
  33. break;
  34. case 'dark':
  35. document.body.classList.add('force-dark-mode');
  36. break;
  37. }
  38. } else {
  39. switch(mode) {
  40. case 'light':
  41. document.body.classList.remove('force-light-mode');
  42. break;
  43. case 'dark':
  44. document.body.classList.remove('force-dark-mode');
  45. break;
  46. }
  47. }
  48. }
  49. }
英文:

This is best handled by setting all your colors in your elements as CSS Custom Properties. e.g.

  1. class MyCustomCard extends LitElement {
  2. static styles = css`
  3. .card {
  4. /* Set custom property and default value */
  5. background-color: var(--sys-color-surface, #FFF);
  6. color: var(--sys-color-on-surface, #000);
  7. ...
  8. }
  9. `;
  10. ...
  11. }

Then you can have a theming.css file at the root of your document. e.g.

  1. &lt;!-- index.html --&gt;
  2. &lt;head&gt;
  3. &lt;link rel=&quot;stylesheet&quot; href=&quot;theme.css&quot;&gt;
  4. &lt;/head&gt;
  1. /* theme.css */
  2. /* light theme */
  3. :root, body.force-light-mode {
  4. --sys-color-surface: #FFF;
  5. --sys-color-on-surface: #000;
  6. ...
  7. }
  8. /* auto dark theme */
  9. @media (prefers-color-scheme: dark) {
  10. :root {
  11. --sys-color-surface: #000;
  12. --sys-color-on-surface: #FFF;
  13. ...
  14. }
  15. }
  16. /* user preference dark mode */
  17. body.force-dark-mode {
  18. /* This can be deduplicated with an @import https://developer.mozilla.org/en-US/docs/Web/CSS/@import */
  19. --sys-color-surface: #000;
  20. --sys-color-on-surface: #FFF;
  21. ...
  22. }

Then you can have a dark theme toggle that toggles the force-*-mode class on body:

  1. class ThemeToggle extends LitElement {
  2. render() {
  3. return html`
  4. &lt;div&gt;Select Theme&lt;/div&gt;
  5. &lt;label&gt;
  6. Light Mode
  7. &lt;input
  8. type=&quot;radio&quot;
  9. @change=${this.onChange(&#39;light&#39;)}
  10. name=&quot;theme&quot;&gt;
  11. &lt;/label&gt;
  12. &lt;label&gt;
  13. Follow System
  14. &lt;input
  15. type=&quot;radio&quot;
  16. @change=${this.onChange(&#39;system&#39;)}
  17. name=&quot;theme&quot;
  18. checked&gt;
  19. &lt;/label&gt;
  20. &lt;label&gt;
  21. Dark Mode
  22. &lt;input
  23. type=&quot;radio&quot;
  24. @change=${this.onChange(&#39;dark&#39;)}
  25. name=&quot;theme&quot;&gt;
  26. &lt;/label&gt;`
  27. }
  28. onChange = (mode) =&gt; (e) =&gt; {
  29. if (e.target.checked) {
  30. switch(mode) {
  31. case &#39;light&#39;:
  32. document.body.classList.add(&#39;force-light-mode&#39;);
  33. break;
  34. case &#39;dark&#39;:
  35. document.body.classList.add(&#39;force-dark-mode&#39;);
  36. break;
  37. }
  38. } else {
  39. switch(mode) {
  40. case &#39;light&#39;:
  41. document.body.classList.remove(&#39;force-light-mode&#39;);
  42. break;
  43. case &#39;dark&#39;:
  44. document.body.classList.remove(&#39;force-dark-mode&#39;);
  45. break;
  46. }
  47. }
  48. }
  49. }

huangapple
  • 本文由 发表于 2023年7月13日 13:19:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76676150.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定