【问题标题】:How can I change color scheme when checkbox is checked?选中复选框时如何更改配色方案?
【发布时间】:2021-09-13 10:25:47
【问题描述】:

我正在尝试为我的网站实现明暗模式。它应该基于prefers-color-scheme 加载,并且用户应该能够在这两个模块之间切换。

我写了这个:

<div id="theme-togle">
    <input id="theme-toggle-dark" type="checkbox" />
    <span id="checkmark-dark"></span>
    <input id="theme-toggle-light" type="checkbox" />
    <span id="checkmark-light"></span>
</div>
@mixin dark-theme {
    --body-color:           #313131;
    --text-color:           #FFFFFF;
    --title-color:          #000000;
    --subtitle-color:       #808080;
    --logo-color:           #FFFFFF;
    --link-color:           #FFFFFF;
    --link-visited-color:   #FFFFFF;
    --quote-color:          #FFFFFF;
    --code-background-color:#787878;
    --text-highlight-color: #D3D3D3;
    --separator-color:      #525252;
}


@mixin light-theme {
    --body-color:           #313131;
    --text-color:           #FFFFFF;
    --title-color:          #000000;
    --subtitle-color:       #808080;
    --logo-color:           #FFFFFF;
    --link-color:           #FFFFFF;
    --link-visited-color:   #FFFFFF;
    --quote-color:          #FFFFFF;
    --code-background-color:#787878;
    --text-highlight-color: #D3D3D3;
    --separator-color:      #525252;
}

:root{
    @include light-theme;
}


#theme-toggle-dark {
    display: none;
}

@media (prefers-color-scheme: dark){
    @include dark-theme;

    #theme-toggle-light {
        display: none;
    }

    #theme-toggle-dark {
        display: block;
    }
}

@media (prefers-color-scheme: light){
    :root{
        @include light-theme;
    }

    .theme-toggle-dark {
        display: none;
    }

    .theme-toggle-light {
        display: block;
    }
}

#theme-toggle-dark:checked + :root{
    @include dark-theme;
}

#theme-toggle-light:checked + :root{
    @include light-theme;
}

它可以根据prefers-color-scheme成功选择默认模式,但我无法使用复选框进行切换。

我怎样才能做到这一点?我正在寻找免费的 javascript 解决方案。

感谢您的帮助

【问题讨论】:

  • :root 不是复选框的直接兄弟,因此您的选择器 #theme-toggle-dark:checked + :root 将不起作用。
  • @Terry 有办法写对吗?
  • 你需要使用 JS。
  • 阅读他正在使用的选择器:... + *,这意味着他正在选择所有直接同级并将 CSS 变量应用到。你的方法不同。
  • 目前除了 JS 没有其他办法。将来,如果 :hassupported by the navigators 就像 body:has(#theme-toggle-dark:checked) {@include dark-theme;} body:has(#theme-toggle-light:checked) {@include dark-theme;} 一样,您将只能使用 CSS 来做到这一点

标签: html css sass color-scheme scss-mixins


【解决方案1】:

您需要重新组织您的 HTML 以使其正常工作。

目前,复选框作为 body 元素的子节点,位于 :root 元素内。这会导致您的选择器失败,因为您使用的是直接兄弟语法。你也不能使用:root

为了让它工作,你的复选框需要是 body 元素中的第一个子元素,然后你需要将选择器应用于其他所有元素。

<body>
    <input id="theme-toggle-dark" type="checkbox" />
    <span id="checkmark-dark"></span>
    <input id="theme-toggle-light" type="checkbox" />
    <span id="checkmark-light"></span>

    ...
</body>
#theme-toggle-dark:checked ~ * {
    @include dark-theme;
}

#theme-toggle-light:checked ~ * {
    @include light-theme;
}

也就是说,这并不是一个真正理想的解决方案,因为使用星号选择器重新绘制所有节点可能会相对繁重,具体取决于页面中的内容量。

最好将您的所有内容包装在一个容器元素中,并且只针对该元素执行应用程序:

<body>
    <input id="theme-toggle-dark" type="checkbox" />
    <span id="checkmark-dark"></span>
    <input id="theme-toggle-light" type="checkbox" />
    <span id="checkmark-light"></span>

    <div id="container">
       ...
    </div>
</body>
#theme-toggle-dark:checked ~ #container {
    @include dark-theme;
}

#theme-toggle-light:checked ~ #container {
    @include light-theme;
}

另外,您可能希望使用radio 输入而不是复选框。选择这两个项目是没有意义的。

或者,您可以考虑只使用一个复选框作为切换开关。这样您就不必跟踪默认的用户偏好状态(必须通过 JavaScript 完成)。

这是一个如何工作的示例:

<body>
    <input id="theme-toggle" type="checkbox" />
    <span id="checkmark-theme"></span>

    <div id="container">
       ...
    </div>
</body>
@media (prefers-color-scheme: dark) {
   #container {
       @include dark-theme;
   }

   #theme-toggle:checked ~ #container {
       @include light-theme;
   }
}

@media (prefers-color-scheme: light) {
   #container {
       @include light-theme;
   }

   #theme-toggle:checked ~ #container {
       @include dark-theme;
   }
}

这是一个工作示例。注意:您需要做一些巧妙的尺寸调整和定位,以便让所有东西都对齐。您可能还需要为切换标签复制一些样式。

@media (prefers-color-scheme: dark) {
   #container {
      background: black;
      color: white;
   }
   
   #toggle:checked ~ #container {
      background: white;
      color: black;
   }
}

@media (prefers-color-scheme: light) {
   #container {
      background: white;
      color: black;
   }
   
   #toggle:checked ~ #container {
      background: black;
      color: white;
   }
}
<input id="toggle" type="checkbox" />
<label for="toggle">Toggle Theme</label>
<div id="container">
  <p>Test</p>
</div>

【讨论】:

  • 感谢您的精彩回答。我将尝试尽快实施。如果我理解正确,是否需要使用两个单选按钮?我希望有一个按钮可以用来在配色方案之间切换。
  • 就个人而言,我可能会使用一个复选框来打开或关闭暗模式。
  • 如果您在回答中这样做,我会在尝试实施之前立即接受它。
  • 我添加了第三个示例,以展示如何使用单个复选框作为反转首选颜色方案的切换开关来完成。
  • 是的,我添加了一个工作示例。它并不完美,您需要根据自己的设计自己做更多的工作,但这应该足以让您入门。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
  • 2016-03-24
相关资源
最近更新 更多