为你的网页添加深色模式

翻译:疯狂的技术宅
原文:https://www.creativebloq.com/how-to/how-to-implement-light-or-dark-modes-in-css

Use light and dark mode in CSS

CSS 规范一直在不断发展。尽管在 CSS 新功能的实现很复杂,但是 CSS 工作组还是决定要把简化版作为新元素添加到规范中。然后由浏览器来实现这些新元素,浏览器自行决定以哪种顺序去实现它们,这就是为什么现在对新功能的支持不匹配的原因。虽然这可能会令人讨厌,但实际上完成了规范的浏览器要好得多。

CSS 工作组的成员来自主要浏览器供应商和 Apple 、Adobe等其他技术公司。 Apple 最近推出了新版的 MacOS,并希望能够在浏览器中检测到新加入的深色模式。为了做到这一点,Apple 推荐了一个新的 5 级媒体查询规范。

@media (prefers-color-scheme: light | dark) 
{ … }

使用这个媒体查询,可以检测用户是否正在使用操作系统的浅色或深色模式。不过目前仅支持 Safari Technology Preview 69 及更高版本,但其他浏览器不应落在后面。

为了测试这个功能,你需要升级到 Mojave 10.14(MacOS)并在“系统偏好设置”中选择“深色”。我们可以通过好几种方式使用这种新的媒体查询来实现不同的主题。在将在本教程中将会探讨其中的一些内容。

01. 设置页面

首先,我们需要有一些 HTML 元素来设置样式,所以先到 CodePen 创建一个新文件并添加一些元素。首先添加一个容器,以便将内容集中起来,然后再添加一些标题和文本。将 CSS 设置为使用 Sass 以便在CSS中使用嵌套。

<div class="content-container">
    <h1>Heading One</h1>
    <h2>Heading Two</h2>
    <hr>
    <p>…</p>
    <p>…</p>
</div>

02. 基本元素的样式

接下来将会添加一些基本样式,其中包含一些来自Google的字体,这样可使的页面看起来更好一些。我们要设置所有基本元素的样式,并应用新的字体大小、颜色和字体。

body {
    font-family: 'Merriweather', serif;
    background-color: #ededed;
    color: #212121;
    padding: 1.618rem;
    line-height: 1.618;
    font-size: 16px;
}

03. 容器的样式

image

为容器设置一个舒适的阅读样式

接下来,为容器设置样式,把内容的行调整为为阅读时舒适的长度。另外还会添加背景颜色和阴影。为了使页面中的内容框居中,在边距属性的左右值上使用关键字 “auto”。

.content-container {
    padding: 1.618rem 3.236rem;
    max-width: 48.54rem;
    margin: 3.236rem auto;
    background-color: #fff;
    box-shadow: 0 0 12px 6px rgba(0,0,0,0.05);
    border-radius: .269666667rem;
}

04. 添加高亮颜色

image

选择一种高亮颜色并生成样式

大多数网站都会在文本中的某处使用其它颜色,但是目前我们只有白色和灰色,所以现在要选择一种高亮颜色并用这种颜色的创建样式。我们使用 span 标签应用颜色,并用它来突出显示文本中的内容。

<span class="text--alpha">Lorem ipsum</span>
.text--alpha {
    color: #c3423f;
}

05. 实现媒体查询

image

现在有了一些样式,就可以实现媒体查询了

现在我们有了一个包含一些基本样式的页面,接着实现媒体查询的方法。让我们包括它并重写一些样式。先从 body 开始。

@media (prefers-color-scheme: dark) 
{
    body {
        background-color: #111;
    }
}

06. 覆盖其余样式

image

现在你可以覆盖其余的样式

现在可以看到媒体查询正在运行并且 body 的背景颜色已经改变,最后需要覆盖所有剩余的样式。

.content-container 
{
    color: white;
    background-color: #212121;
}
.text--alpha {
    color: #50a8d8;
}

07. 可维护性

虽然刚刚完成的 Demo 看上去挺不错,而且可以在小型的网站上进行维护,但这种方法对于更大的项目来说将会是一场噩梦,因为其中包含有许多不同的元素,这些元素都需要被重写。同时在上面的例子中大量使用级联,而大型系统可能需要更多的特异性才能定位所有元素。

08. 采取另一种方式

image

为了快速实现深色模式,只需用 CSS 滤镜的 “invert”……

那怎样才能解决这个问题呢?我们可以使用 CSS 滤镜的 “invert”,将其应用于 HTML 并反转所有颜色,从而为我们提供 “深色模式”。

@media (prefers-color-scheme: dark) {
    html {
        filter: invert(100%);
    }
}

09. 添加图片

image

当然,你的照片看起来会像这样

虽然滤镜方法在我们文档中的内容上起了作用,但是看起来不太好 —— 例如盒子阴影也被倒置了,这看起来很奇怪。我们已经失去了对样式的控制,当你用了彩色背景时,会出现一个更大的问题。看看你的照片变成了什么样子。

10. 使用自定义属性

到目前为止,我们探索过的方法要么会失去对样式的控制,要么需要大量的维护才能确保所有内容都在深色模式下更新。不过还有一种方法可以解决这个问题:可以用自定义属性来定义颜色,然后使用媒体查询覆盖它们。

11. 创建自定义属性

为了使用自定义属性,我们在:root元素内的CSS顶部定义它们。根元素具有与 HTML 相同的范围,因此可以全局使用。我们需要确定变量名称并定义它们的值。

:root {
    --background-color: #ededed;
    --page-background: #fff;
    --text-color: #212121;
    --color-alpha: #c3423f;
}

12. 应用自定义属性

现在定义了一些可以在CSS中使用的自定义属性。我们将从正文开始,并应用背景和文本颜色。为了使用自定义属性,我们用了 var(--custom-property-name)语法。

body {
    background-color: var(--background-color);
    color: var(--text-color);
}

13. 应用其余的属性

使用相同的方法,我们还可以更新容器的background-colortext-alpha类的color,让它们也使用自定义属性。现在,页面中所有得颜色都使用自定义属性进行控制。

.content-container {
    background-color: var(--page-background);
}
.text--alpha {
    color: var(--color-alpha);
}

14. 重新添加媒体查询

现在重新添加媒体查询,但这次我们可以覆盖其中的自定义属性值。把它放在原始根定义之后,在媒体查询中,可以简单地为所有颜色自定义属性选择新值。

@media (prefers-color-scheme: dark) {
    :root {
        --background-color: #111;
        --page-background: #212121;
        --text-color: #ededed;
        --color-alpha: #50a8d8;
    }
}

15. 完全控制

自定义属性使我们可以完全控制选择自己的颜色和其他属性。能够对页面容器上的边框阴影进行更新,使其在使用深色模式时不太透明。索引我们需要为页面阴影创建一个新的自定义属性。

:root {
    …
    --page-shadow: 0 0 12px 6px rgba
    (0,0,0,0.05);
}

16. 应用阴影

现在我们已经有了另一个自定义属性,接下来需要将它应用于页面上正确的元素。然后覆盖root元素中的值,以降低透明度。

@media (prefers-color-scheme: dark) {
    :root {
        …
        --page-shadow: 
            0 0 12px 6px rgba(0,0,0,0.33)
        ;
    }
}
.content-container {
    …
    box-shadow: var(--page-shadow);
}

17. 添加图像

image

添加图像并将其浮动到内容旁边

现在将图像添加回我们的内容,然后可以添加一些基本样式来将图像浮动到内容旁边。

img {
    width: 100%;
    height: auto;
    float: left;
    max-width: 300px;
    margin-right: 1.618rem;
    margin-bottom: 1.618rem;
}

可以看到,由于没有使用任何滤镜,所以图像在两个主题之间不会改变。

18. 添加更多组件

现在我们已经获得了自定义属性,可以继续向页面添加元素,并使用变量为它们设置样式。让我们创建一个按钮类,并在页面中添加一个按钮。

.button {
    display: inline-flex;
    font-family: inherit;
    background-color: var(--color-alpha);
    color: var(--text-color);
    padding: 1.618rem 3.236rem;
    border: 0 none;
    border-radius: 0.25rem;
    text-decoration: none;
}

19. 创建按钮悬停样式

使用相同的变量,还可以创建可用于两个主题的悬停样式。为了实现这一点,当用户将鼠标悬停在按钮上并转换这些属性时,我们将反转颜色。

.button {
    …
    transition: background-color 150ms, 
    color 150ms;
    &:hover {
        background-color: var(--text-color);
        color: var(--color-alpha);
    }
}

20. 制作按钮自定义属性

自定义属性与常规 CSS 元素具有相同的范围,这意味着可以用更加具体的选择器覆盖它们。可以利用这个特性并创建一些作用于按钮的变量。

.button {
    --button-background: var(--color-alpha);
    --button-text: var(--background-color);
    background-color: var(--button-background);
    color: var(--button-text);
    …
}

21. 利用 scope

image

使用 scope 为按钮创建不同的样式和交互

我们可以利用 scope 为深色和浅色主题的按钮创建不同的样式和悬停交互。可以根据媒体查询或元素的状态修改变量的值,而不是像往常一样使用新值重复属性。

.button {
    …
    &:hover {
        --button-background: #ae3937;
        @media (prefers-color-scheme: dark) {
            --button-background: #2e98d1;
            --button-text: var(--background-
            color);
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,375评论 1 45
  • HTML 5 HTML5概述 因特网上的信息是以网页的形式展示给用户的,因此网页是网络信息传递的载体。网页文件是用...
    阿啊阿吖丁阅读 3,815评论 0 0
  •   DOM 1 级主要定义的是 HTML 和 XML 文档的底层结构。   DOM2 和 DOM3 级则在这个结构...
    霜天晓阅读 1,407评论 1 3
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,979评论 4 60
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,039评论 0 3