web 暗黑模式探索

由于写一个基于 Remix + Mdx 的博客项目,其中探索的 web 端的暗黑模式做法。总结成一点:

自动:CSS 变量切换与 CSS 媒体查询

手动:CSS 变量切换与 JS 交互

基础知识

  1. prefers-color-scheme 媒体查询
@media (prefers-color-scheme: dark) {
  /* 暗黑模式下的样式 */
}

@media (prefers-color-scheme: light) {
  /* 亮色模式下的样式 */
}
  1. 特殊的 color-scheme 属性

操作系统颜色方案的常见选择为“亮色”和“暗色”,或“日间模式”和“夜间模式”。当用户选择其中一种颜色方案时,操作系统会对用户界面进行调整,包括表单控件、滚动条和 CSS 系统颜色的使用值。

color-scheme: normal; // 未指定任何配色方案,因此应使用浏览器的默认配色方案呈现
color-scheme: light; // 使用操作系统亮色配色方案渲染元素
color-scheme: dark; // 使用操作系统深色配色方案渲染元素
color-scheme: light dark; // 要将整个页面配置为使用用户的配色方案首选项
color-scheme: only light; // 禁止用户代理覆盖元素的颜色方案, 仅仅使用 light

除了 css 变量还要关注哪些问题?

  • 可访问性 Accessibility) 在安和模式中可访问性更多的关注 颜色 可见性。
  • 颜色切换动画, 以下是一个简单的实现:
body {
  transition: background-color 0.3s ease;
}

一个最简单的暗黑模式

@media (prefers-color-scheme: dark) {
  html {
    filter: invert(90%) hue-rotate(180deg); // 颜色反转 90%, 色相旋转 180 deg
  }

  img, video, svg, div[class*="language-"] { 
  // 对图片,视频, svg 和 div 中 language- 开头的类,反转 110% 度。
    filter: invert(110%) hue-rotate(180deg);
    opacity: .8;
  }
}

最简单的样式只关注 css 部分,随系统控制样式变化。

一个最简单手动挡 js 运行时媒体查询

使用 vite 初始化一个 原生 TS 项目,添加按钮,实现简单的 浏览器 js 运行时中切换亮色和暗色:

  • 添加 html
<div class="schema-mode">
    <button id="change-mode-id" type="button">change 颜色</button>
</div>
  • 添加 js 交互代码
export function changeSchemaMode(element: HTMLButtonElement) {
  const setMode = () => {
    const html = document.documentElement.getAttribute("class");
    console.log(html);

    if (!html) {
      document.documentElement.classList.add("dark");
    } else {
      document.documentElement.classList.remove("dark");
    }
  };

  element.addEventListener("click", () => setMode());
}
  • 添加 css 代码
:root {
  --bg: #fff;
}

html.dark {
  color-scheme: dark;
}

.dark {
   --bg: #272020;
}

body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--bg);
}

点击按钮切换按钮实现 css 颜色的切换。这种方式缺点也很明显,刷新之后页面不能保留状态。

保留暗黑模式状态

在实现配合框架中实现暗黑模式的时候,可能我们问题会发生转移,变成如何存储 暗黑模式 交互式产生的变量。本质上使用纯 css 变量 + css 媒体查询,使用的是,系统的变量(随系统的变量的变化而变化。)

渲染方式 说明 结果
客户端渲染 js 运行时修改 刷新即消失,体验不好
客户端渲染 js 运行时 + 本地存储同步状态 体验良好
ssr js 运行时 刷新即消失
ssr js 运行时 + cookie + session 辅助 体验良好
ssr js 运行时 + localstorage 页面闪动

以下 Remix 中使用 session + cookie 存储的页面变化,实现的暗色模式。

但这里其实实现暗色模式其实已经需要前后端配合,前后将选择的 theme 保存在 session + cookie 中存储起来。来保证页面不会闪动。

其他的:灰色模式

灰色模式使用滤镜模式实现,用于一些特定的样式技巧。

html{
    -webkit-filter : grayscale(100%);
    -moz-filter: grayscale(100%);
    -o-filter: grayscale(100%);
    filter: grayscale(100%);
    filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}

css 滤镜注意使用 css 的兼容性。

项目推荐

  • remix-mdx-blog 中实践了 Remix 框架的诸多技巧, Remix 目前并不流行,但是 Remix 是一个好的全栈框架,目前正处于向 V2 版本的开发之中。其中暗黑模式操作使用与 Remix 框架,如果你对小技术的变化演进感兴趣,不妨尝试,如果能帮助到你,不妨给个 star 或者请作者喝一杯奶茶。

小结

这篇文章主要讲解 css 关注暗黑模式的探索,最简单的暗黑模式,手动控制不同的样式,以及可访问性(颜色的可访问性),在 vite + 原生 TS 项目中实现手动暗黑模式切换。有了这些基础实现一个小的暗黑模式难度就不到的,后面是集成到现在带有 SSR 渲染框架中,因为像 React 中 SSR 存在水合的过程,使用 本地存储,保存状态会存在山东等问题,本地存储不适合 SSR 的框架,所以存储方式改为 session + cookie 的方式,说白就是存到了服务端保证SSR 渲染出 html 的时候, html 属性中带有正确的属性,不至于水合的过程发生变化。

原文链接:https://juejin.cn/post/7238185960058929211 作者:进二开物

(0)
上一篇 2023年5月29日 上午10:53
下一篇 2023年5月29日 上午11:03

相关推荐

发表回复

登录后才能评论