一如既往地感谢其他更聪明的人,我实现了一个模式切换,为您提供了另一种选择。
去年六月,我解释了如何根据Salma Alam-Naylor 的代码,向此站点添加明/暗模式切换。今天,我再次感谢其他更聪明的人,我将这个开关变成了一个三态开关,允许您在浅色模式、深色模式或默认模式下查看此网站。
顺其自然
在去年的那篇文章中,我指出我接受这样的论点,即简单地将亮/暗切换留给一个人的操作系统设置并不允许人们偶尔希望特定站点以默认模式以外的模式出现。 。然而,在接下来的几个月里,我意识到我没有考虑到那些不希望网站对其默认设置进行混乱的人。简而言之,选择应该包括不理会事情,这将需要三态开关而不是双态切换(我猜,这是唯一的切换类型)。
我确实找到了很多关于这种转换的优秀文章,尤其是 Aleksandr Hovhannisyan 去年 11 月发表的这篇文章。尽管如此,最后,我发现他们的许多代码示例对我来说有点难以理解,所以我最终制作了一个更简单的(尽管不是那么DRY )版本。
(部分)代码
首先,网站标头模板的 HTML 1 (当然不是head
):
<!-- This replaces a `button` from the Alam-Naylor method. --> < div class = "nScrHidden themeToggle" data-theme-toggle > < label for = "lightMode" class = "lightLabel" aria-label = "Select light mode" title = "Light mode" > < input type = "radio" name = "toggleTheme" id = "lightMode" /> ? </ label > < label for = "autoMode" class = "autoLabel" aria-label = "Select auto mode for OS theme choice" title = "Auto mode" > < input type = "radio" name = "toggleTheme" id = "autoMode" /> ? </ label > < label for = "darkMode" class = "darkLabel" aria-label = "Select dark mode" title = "Dark mode" > < input type = "radio" name = "toggleTheme" id = "darkMode" > ? </ label > </ div >
然后,JavaScript:
模式切换-auto.js
const buttonLight = document . getElementById ( "lightMode" ) const buttonAuto = document . getElementById ( "autoMode" ) const buttonDark = document . getElementById ( "darkMode" ) const htmlDoc = document . querySelector ( "html" ) const themeStatus = localStorage . getItem ( "theme" ) goAuto = () => { localStorage . removeItem ( "theme" ) htmlDoc . removeAttribute ( "data-theme" ) } goLight = () => { localStorage . setItem ( "theme" , "light" ) htmlDoc . setAttribute ( "data-theme" , "light" ) } goDark = () => { localStorage . setItem ( "theme" , "dark" ) htmlDoc . setAttribute ( "data-theme" , "dark" ) } if ( themeStatus === undefined || themeStatus === "auto" ) { goAuto () } else if ( themeStatus === "light" ) { goLight () } else if ( themeStatus === "dark" ) { goDark () } buttonLight . addEventListener ( "click" , () => { goLight () }) buttonAuto . addEventListener ( "click" , () => { goAuto () }) buttonDark . addEventListener ( "click" , () => { goDark () })
至于让它发挥作用的样式,我主要借鉴了 Hovhannisyan 文章的 “CSS:主题变量”部分。由于我在造型中做了很多浅色/深色模式的东西,所以我不会在这里放弃所有这些。
怎么运行的
与它所替换的切换开关一样,此开关将data-theme="light"
或data-theme="dark"
添加到页面的html
标记中,然后网站的样式会相应地进行调整。但是,与切换不同的是,该开关还允许您选择自动模式,这会删除任何此类data-theme
属性,以便您的明/暗设置将照常进行。事实上,我现在将自动模式作为默认模式。
同样, localStorage cookie会记住您的设置,以便您再次访问此处时使用;或者,如果您选择自动模式,代码将删除cookie。新访客显然还没有设置 cookie,保证这样的新访客将看到他/她选择的模式;相比之下,早期的切换默认为新访问者使用深色模式。虽然对于许多人来说,这可能是比灯光模式更安全的选择,但新的默认设置“您选择的设置”更有意义。
触发所有这些的 UI 项目是单选按钮,每个按钮都有一个opacity: 0
设置,绝对定位,顶部有一个 Unicode 字符来象征其功能:?( ?
的 HTML 实体)表示灯光模式,? ( ?
) 表示自动模式,? ( ?
) 表示深色模式。 (如果您在浅色模式下查看此内容,您可能需要至少短暂切换到深色模式,以便可以更轻松地看到这些字符;幸运的是,我的标题目前在所有模式下都有深色背景。)我认为这是比以前使用 SVG 更简单,尤其是在我在多个平台上进行的测试表明对这些 Unicode 字符有足够的支持以让它们完成这项工作之后。
顺便说一句:在研究这个问题时,我最初采用了 Hovhannisyan 对可见单选按钮的使用。最后,我决定不这样做;但是,如果您选择使用可见的单选按钮为您自己的网站调整我的代码,请注意您也需要管理这些按钮的状态 –即,因此当其模式处于播放状态时将检查相应的按钮- 因此,可能必须使用另一个 localStorage cookie 来实现此目的。例如:
// previous `const` declarations above const radioStatus = localStorage . getItem ( "radios" ) goAuto = () => { localStorage . removeItem ( "theme" ) localStorage . setItem ( "radios" , "auto" ) // additional htmlDoc . removeAttribute ( "data-theme" ) buttonAuto . checked = true // additional buttonLight . checked = false // additional buttonDark . checked = false // additional } // And so forth in the rest of it...
参考
- Salma Alam-Naylor,“ JavaScript 中最好的明暗模式主题切换” (2023-06-19) 。
- 乔什·W·科莫(Josh W. Comeau),“追求完美的黑暗模式” (2020-04-22) 。
- Aleksandr Hovhannisyan,“完美的主题切换组件” 2023-11-21 。
- Tamas Piros“三态明/暗主题切换” (2021-04-20) 。
- Bramus Van Damme,“ 使用 Vanilla JavaScript 寻求完美的黑暗模式切换” (2020-04-26) 。