夜间模式🌚🌝与混合模式的区别

2025-06-10

夜间模式🌚🌝与混合模式的区别

我在准备我的演讲《This World Mixed and Blended》 (这些幻灯片需要彩色字体支持,例如 FireFox / Safari)时萌生了实现夜间模式 的想法。最初的想法只是为了展示,而且目前浏览器支持有限mix-blend-mode: difference

尽管如此,我还是把它实现到我的开发博客上,并且玩得很开心。所以这篇文章就是关于这个的。同时,随着我进一步思考,我发现这或许可以成为实现夜间模式的一种更合适的方式。让我也分享一下背后的一些想法。

请注意,这不是实现暗黑模式的标准方法。想了解大家通常的做法,你可以看看Dan Abramov 在 Overacted 上的做法,或者看看这篇文章

理解mix-blend-mode: difference

mix-blend-mode: difference是 CSS 支持的混合模式之一,具体定义在“合成与混合级别 1”中。混合模式则指定了图形堆叠时颜色的混合方式。图形不限于图像。任何渲染的图形、div 内容、文本、表情符号🌚🌝、SVG 等都可以参与混合。

我想将其视为浏览器在绘制新元素时与我们核对的过程:“嘿,看来我绘制的下一个像素是红色的,但目前我看到地面是蓝色,您是否希望我将这些颜色组合在一起,如果是的话,怎么做?”

混合模式允许我们创建一些非常有趣的效果,例如在图像上叠加文本,同时直接在浏览器中显示图形的纹理:

合成和混合级别 1中的混合模式示例

定义

mix-blend-mode: difference具体来说,是一种混合模式,其定义为取两种颜色之间的差异的绝对值:

difference(A, B) = |A - B|
Enter fullscreen mode Exit fullscreen mode

这是实际计算的抽象,其中对于每种颜色,我们用三个数字分别代表 R、G 和 B 通道。例如,

difference(
    rgb(255, 255, 255),
    rgb(0, 100, 200)
) = rgb(255, 155, 55)
Enter fullscreen mode Exit fullscreen mode

同时,取绝对值使得运算可交换,即B(A, B) = B(B, A)。换句话说,无论哪个图形放在另一个图形上面,结果都是一样的。

直觉

混合模式的“差值”究竟起什么作用?定义看似简单。然而,在实际看到最终颜色之前,我们的大脑可能无法很好地感知到最终颜色的变化。举个例子,difference(white, red)本质上是在推断红色的补色,也就是青色。但是,除非你真正看到它,否则你怎么能“看到”它呢

下面的笔是通过混合白色和红色的相交条纹创建的。

也许正是因为它的效果难以察觉,我们可以利用它创建一些对比鲜明的视觉效果来在 UI 中引发惊喜,就像Sven Wolfermannmix-blend-mode: difference的这个一样

这个设计启发了我思考如何使用差异来创建暗模式。

使用以下方式实现暗黑模式mix-blend-mode: difference

它是如何工作的?

background: white这个想法很简单:当夜间模式打开时,用 和的全屏 div 覆盖您的网站mix-blend-mode: difference,并省去再次定义所有颜色的麻烦😉

.dark-mode-screen {
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  background: white;
  mix-blend-mode: difference;
}
Enter fullscreen mode Exit fullscreen mode

但为什么呢?

这个思维过程涉及数学家最喜欢的两个数字:0 和 1。

在单位空间中,0 表示,1 表示

在 RGB 颜色中,0 表示黑色,1(100% 或 255)表示白色。

现在让我们想象一下我们的博客网站,假设我们现在有一个白色背景和一个黑色前景。如果我们把这个页面与白色的差异取下来,我们会得到什么?

  • 背景:目前是白色,和白色没什么区别,也就是黑色
  • 前景:目前是黑色,代表什么都没有,白色和什么都没有的区别就在于白色

现在我们有了黑色背景白色前景,看看那是什么?反转(深色)主题 :)

此外,当提取页面与白色之间的差异时,原始背景和前景之间的对比度会自动保留。这不仅适用于黑色和白色。事实上,我使用原始主题“Dracula”的代码块在反转后会呈现出漂亮的棕褐色调。

过渡

缩放 div

我在页面底部固定了一个开关。当夜间模式切换时,我会将这个开关放大并覆盖整个页面。这种效果在某种程度上展现了最初的用户体验设计。

不透明度

如果您更喜欢更细微的切换,或许微调一下opacity是个更好的选择,混合模式也能达到同样的效果。由于过渡效果带有缓和时间的功能,这或许是大多数实现夜间模式的网站和博客所采用的过渡界面。

隔离不打算混合的元素

如前所述,mix-blend-mode适用于任何图形。但是,在实现暗黑模式时,某些元素可能不需要混合。例如,特定颜色的徽标、表情符号等。要指定这种情况,您可以在这些元素上放置isolation: isolate(引用)。请注意,这会在被隔离的元素上创建一个堆叠上下文。

/* twitter logo and emoji should not blend */
.twitter-logo,
.emoji {
  isolation: isolate; 
}

/* elements that create their a stacking context are automatically isolated */
.footer {
  z-index: 1;
}
Enter fullscreen mode Exit fullscreen mode

为你的黑暗模式选择一种色调

如前所述,取页面与白色之间的差异就像直接取补色一样。您不必将颜色选择限制为白色。事实上,您可以选择任何颜色来取差异。为了在网站最初采用浅色背景的情况下实现较暗主题的效果,您可以考虑任何相对较浅的颜色:

这些是我遇到的一些技术细节。如果您在尝试过程中遇到任何问题,请随时告诉我,我很乐意为您提供帮助。

要在代码中查看此内容,请查看此 CodePen:

限制

(除了有点怪异之外😅)

  • 你没有完整的颜色范围。这省去了你指定更多颜色的麻烦,但你会失去对深色的控制——它们会从浅色中推断出来。然而,这可能不是一个限制,而是一个设计选择。
  • 的浏览器支持mix-blend-mode仍然不是最佳的,您只能使用非 IE 且相对较新版本的浏览器
  • 由于其逐像素和逐通道计算,性能也可能是一个问题。暂时不要用它做疯狂的动画。

下次再见🤞

混合模式源自计算机图形学。我记得几年前第一次在 Photoshop 中玩它们。如今浏览器功能越来越强大,我们看到了浏览器渲染原生的复杂图形功能。但这并不意味着我们应该在浏览器中实现完整的 Photoshop,也不应该将我们的想象力局限于此。浏览器和网页有各自的使用场景和目标,以及不同的限制。或许我们应该像欢迎新居民一样欢迎它们,并探索它们在各自领域的原生用例。

再次感谢CodePen 上的这个动画,它可爱极了,让人一眼就印象深刻。不妨把鼠标悬停在它上面🙈

我希望这可以成为您关于混合模式的一个友好发现,并且希望您和我一样享受乐趣。

鏂囩珷鏉ユ簮锛�https://dev.to/wgao19/night-mode-with-mix-blend-mode-difference-23lm
PREV
为什么运行 `yarn update` 不会更新我的 `package.json` 为什么运行 `yarn update` 不会更新我的 package.json
NEXT
使用 NodeJS 中的多线程同时上传多个文件