如何根据用户偏好在 Drupal 8(或 9)中在深色和浅色模式之间切换
已发表: 2020-09-15让您的用户可以根据自己的喜好自由定制他们的界面,这有多棒? 虽然许多用户喜欢浅色界面(浅色背景和深色文字),但一些用户选择深色界面(深色背景和浅色文字)。 较暗的界面被认为是很酷和时尚的,而有些人还认为它可以减轻眼睛的压力,尤其是对于在屏幕前花费大量时间的开发人员。 我相信为您的用户提供一个选项在可访问性和用户体验方面是一个巨大的胜利。 有几种方法可以实现这一点。 在本文中,我们将讨论如何在深色/浅色网页设计模式之间切换,并在 Drupal 8 或 Drupal 9 中实现这一点。

我们将专注于两种方法来实现这一点 -
1. 仅使用 CSS。
2.实现CSS & JS切换开关
仅使用 CSS
要在任何仅使用 CSS 的网站上实现暗模式,必须牢记一些系统要求。 其中一项重要要求是系统范围的暗模式。 如果用户更喜欢在他的 PC 上使用深色模式,那么该用户将获得一个网站,该网站显示带有浅色文本的深色背景。 首选颜色方案(媒体查询)用于识别用户是否已请求系统使用浅色或深色主题。
执行:
1. 声明 CSS 变量。
2. 在需要的地方使用变量。
结果:
注意:要在一些不受支持的设备上模拟结果,只需按 F12 进入 DevTool。 接下来,按CTRL+SHIFT+P,然后搜索prefers-color-scheme: dark 并按回车键。
实现 CSS 和 JS 切换开关
如果我们采用这种方法,那么我们就不需要担心系统要求。 只需编写几行 CSS 和 JS,您就应该准备好了。 一旦我们初始化了变量,我们就可以在我们的样式表中引用这些变量。 这将是在深色和浅色模式之间切换的 HTML 结构。

并且某些 CSS 行应该会导致此切换。

最后一部分是添加一些 JavaScript 来将它们联系在一起。
● 存储用户偏好以备将来访问
● 在加载网站时检查保存的用户偏好(如果有)
而已! 查看下面的完整演示。
或单击此处查看演示。
在 Drupal 8(或 Drupal 9)中实现暗/亮切换
要开始创建自定义 Drupal 8 主题,请参阅此处的精彩文章。 现在让我们开始创建一个主题来展示如何在 Drupal 8 或 Drupal 9 中使用深色主题/浅色主题。
文件结构将如下所示:

现在,使用以下代码更新page.html.twig 中的标题部分。
<header aria-label="Site header" role="banner"> <div class="container"> <div class="header"> {{ page.branding }} {{ page.navigation }} <div class="switch-wrapper"> <label class="switch" for="checkbox"> <input type="checkbox"/> <div class="slider round"></div> </label> </div> </div> </div> </header> HTML 结构的其余部分将取决于您的设计或要求。
一旦您完成了 HTML 结构,就可以通过在 CSS 中设置元素样式来使它们看起来更漂亮。
首先,您必须创建所有默认变量,这些变量将负责亮/暗模式下的颜色。
style.css :root { --color-background: #f0f0f0; --color-header: rgb(14, 33, 141); --color-header-text: #aecafa; --color-text: #2c0000; --color-card-bg: #fff; --color-link: rgb(255, 0, 0); } /* Variable decleration for dark mode */ [data-theme="dark"] { --color-background: #1a1a1a; --color-header: #aecafa; --color-header-text: 0e218d; --color-text: #d3d3d3; --color-card-bg: #435561; --color-link: #24ce24; }现在您已经完成了变量的定义,是时候向 Header 部分添加样式以获得所需的结果了。
style.css .header { display: flex; justify-content: space-between; align-items: center; padding: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; background-color: var(--color-header); } .header a { color: var(--color-header-text); text-decoration: none; font-weight: bold; } .region-navigation { display: flex; justify-content: center; } ul.menu { display: flex; justify-content: center; } ul.menu li { margin-right: 30px; } .switch-wrapper { display: flex; align-items: center; } .switch { display: inline-block; height: 34px; position: relative; width: 60px; } .switch input { display: none; } .slider { background-color: white; bottom: 0; cursor: pointer; left: 0; position: absolute; right: 0; top: 0; transition: 0.4s; } .slider:before { background-color: rgb(255, 196, 0); bottom: 4px; content: url("../assets/sunny-day.svg"); height: 26px; left: 4px; position: absolute; transition: 0.4s; width: 26px; } input:checked + .slider { background-color: rgb(36, 36, 36); } input:checked + .slider:before { transform: translateX(26px); content: url("../assets/night.svg"); background-color: rgb(59, 116, 223); } .slider.round { border-radius: 34px; } .slider.round:before { border-radius: 50%; }style.css .header { display: flex; justify-content: space-between; align-items: center; padding: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; background-color: var(--color-header); } .header a { color: var(--color-header-text); text-decoration: none; font-weight: bold; } .region-navigation { display: flex; justify-content: center; } ul.menu { display: flex; justify-content: center; } ul.menu li { margin-right: 30px; } .switch-wrapper { display: flex; align-items: center; } .switch { display: inline-block; height: 34px; position: relative; width: 60px; } .switch input { display: none; } .slider { background-color: white; bottom: 0; cursor: pointer; left: 0; position: absolute; right: 0; top: 0; transition: 0.4s; } .slider:before { background-color: rgb(255, 196, 0); bottom: 4px; content: url("../assets/sunny-day.svg"); height: 26px; left: 4px; position: absolute; transition: 0.4s; width: 26px; } input:checked + .slider { background-color: rgb(36, 36, 36); } input:checked + .slider:before { transform: translateX(26px); content: url("../assets/night.svg"); background-color: rgb(59, 116, 223); } .slider.round { border-radius: 34px; } .slider.round:before { border-radius: 50%; }
请注意,样式可能会根据您的要求而有所不同。 完成所有样式后,现在是在 Jquery 代码中编写一些功能的时候了。 Jquery 代码看起来像这样(在我们的例子中是 script.js)

script.js (($, Drupal) => { Drupal.behaviors.mainMenu = { attach(context) { const toggleSwitch = document.querySelector( '.switch input[type="checkbox"]' ); const currentTheme = localStorage.getItem("theme"); if (currentTheme) { document.documentElement.setAttribute("data-theme", currentTheme); if (currentTheme === "dark") { toggleSwitch.checked = true; } } function switchTheme(e) { if (e.target.checked) { document.documentElement.setAttribute("data-theme", "dark"); localStorage.setItem("theme", "dark"); } else { document.documentElement.setAttribute("data-theme", "light"); localStorage.setItem("theme", "light"); } } toggleSwitch.addEventListener("change", switchTheme, false); }, }; })(jQuery, Drupal);script.js (($, Drupal) => { Drupal.behaviors.mainMenu = { attach(context) { const toggleSwitch = document.querySelector( '.switch input[type="checkbox"]' ); const currentTheme = localStorage.getItem("theme"); if (currentTheme) { document.documentElement.setAttribute("data-theme", currentTheme); if (currentTheme === "dark") { toggleSwitch.checked = true; } } function switchTheme(e) { if (e.target.checked) { document.documentElement.setAttribute("data-theme", "dark"); localStorage.setItem("theme", "dark"); } else { document.documentElement.setAttribute("data-theme", "light"); localStorage.setItem("theme", "light"); } } toggleSwitch.addEventListener("change", switchTheme, false); }, }; })(jQuery, Drupal);
并且不要忘记将您的 JS 和 CSS 文件包含在您的 theme_name.libraries.yml 文件中。
global-styling: version: 1.x css: theme: css/style.css: {} js: js/script.js: {} dependencies: - core/jquery - core/drupalglobal-styling: version: 1.x css: theme: css/style.css: {} js: js/script.js: {} dependencies: - core/jquery - core/drupal
现在清除站点缓存以查看结果。 你的最终结果应该是这样的:

