使用 CSS 自定义属性的简易网站主题
CSS 属性:快速概览
主题定制用例
结论
随着黑暗模式的出现,网站主题定制正在成为一种期望而不是一项功能。
许多网站更进一步,允许用户从多个主题中进行选择(例如dev.to):
对于某些网站来说,完全自定义网站主题可能有些过度,但在进行网页设计和开发时,我们仍然应该牢记这一点。值得庆幸的是,现代 CSS 包含一些功能,可以轻松实现网站自定义。其中大部分功能都归结为 CSS 自定义属性。
CSS 属性:快速概览
CSS 自定义属性允许我们在 CSS 中定义可复用的变量,而无需预处理器。它们并非新技术;大多数现代浏览器自 2016 年起就已支持它们。而且由于它们是变量,我们可以动态更新它们。
自定义属性可以在任何元素上通过在属性名称前添加 前缀来定义--
。如果我们想在元素上创建可复用的属性root
,可以像这样定义它们(这些示例取自MDN):
:root {
--first-color: #488cff;
--second-color: #ffff8c;
}
我们可以通过var()
关键字在子元素中访问这些属性:
#firstParagraph {
background-color: var(--first-color);
color: var(--second-color);
}
#secondParagraph {
background-color: var(--second-color);
color: var(--first-color);
}
#container {
--first-color: #48ff32;
}
为了演示实际效果,我在下面的示例中定义了三种不同的颜色。当复选框被选中时,CSS 属性会更新,并且引用它们的所有地方的颜色都会改变:
自定义属性可以做很多有用的事情。我推荐阅读Michael Riethmuller 的这篇精彩文章,以便更深入地了解 CSS 自定义属性、如何使用它们以及它们与预处理器变量的区别。
主题定制用例
由于自定义属性可以重复使用并动态更新,因此非常适合主题定制。让我们看看如何使用自定义属性来定制网站。
实现黑暗模式
为网站添加暗黑模式最直接的方法是通过prefers-color-scheme
媒体查询。此媒体查询通常与用户操作系统的主题相对应。
因此,如果我们像这样定义一些范围属性:
main {
--primary-color: cyan;
--secondary-color: orange;
--tertiary-color: yellow;
}
我们可以在媒体查询中简单地更新它们的值:
@media (prefers-color-scheme: dark) {
main {
--primary-color: gray;
--secondary-color: darkgray;
--tertiary-color: lightgray;
}
}
任何使用这些属性的元素都会在用户主题更改时动态更新。实际操作如下:
自定义主题选择
虽然prefers-color-scheme
这是一个很好的起点,但有时我们希望让用户能够随意选择主题。
如果您已设计网站以利用自定义属性,我们可以相当轻松地实现这一点。我们只需修改它们即可,这可以通过 CSS 或 JavaScript 来实现。
使用 CSS 修改自定义属性
自定义属性与任何其他 CSS 一样,只要我们有适当的选择器就可以更新。
如果你检查我之前示例中的 CSS,你会注意到我已将自定义属性的作用域限定在main
元素上。当复选框被选中时,选择器会更新其内部的作用域属性。这会导致main
元素内的所有元素都使用新值进行更新:
虽然这种方法实现起来很快,但 CSS 选择器可能有些不稳定(并且依赖于我们的 HTML)。此外,在大多数情况下,我们希望保存用户的主题选择。JavaScript 为我们提供了更大的灵活性。
使用 Javascript 修改自定义属性
我们可以使用该setProperty()
方法从 Javascript 更新我们的自定义属性。
如果我们有一些针对main
元素的自定义属性,我们可以在 Javascript 中查询它并调用setProperty()
以将其属性更新为新值:
在伪类中定义自定义属性是很常见的。在这种情况下,可以通过调用根元素:root
来更新自定义属性:setProperty
虽然这些示例只改变了几个div
元素,但同样的技巧也可以用来改变整个网站的主题。为了演示这一点,我修改了HTML5UP 的一个模板,使其大多数背景、文本颜色和强调色都使用了自定义属性。然后,我添加了一个切换按钮,用深色值来更新这些属性:
主题切换的代码与上面的 CodePens 非常相似。我在 Javascript 中定义了几个“Theme”对象:
const darkTheme = {
"--accent-color": "#4acaa8",
"--background-color": "#343737",
"--active-scroll-background": "#343737",
"--color-text": "white",
"--sidebar-color": "#444c48"
};
const lightTheme = {
"--accent-color": "#4bcdab",
"--background-color": "#f0ffff",
"--active-scroll-background": "#f0ffff",
"--color-text": "#777",
"--sidebar-color": "#4bcdab"
};
然后,当按下切换按钮时,我使用给定“主题”的属性更新在根元素上定义的自定义属性:
function applyTheme(theme) {
let root = document.documentElement;
root.style.setProperty("--accent-color", theme["--accent-color"]);
root.style.setProperty("--background-color", theme["--background-color"]);
root.style.setProperty(
"--active-scroll-background",
theme["--active-scroll-background"]
);
root.style.setProperty("--color-text", theme["--color-text"]);
root.style.setProperty("--sidebar-color", theme["--sidebar-color"]);
}
通过这样的主题自定义实现,向网站添加新主题就像创建一个新的主题对象一样简单。我们可以根据现有的工具,通过本地存储或数据库来保存用户的偏好设置。
自定义颜色选择
一些网站和应用允许用户直接创建和修改主题。同样,我们可以使用setProperty()
来更新自定义属性,使其具有任意值,包括暴露给用户输入的值。
在下面的 Codepen 中,第一个方块的颜色以及所有方块的边框都作为输入元素显示。提交表单时,这些值会更新并反映在结果中:
当然,我们可以扩展它,以公开整个网站或应用程序中使用的各种属性。然后可以导出或保存这些首选项,以记住用户的选择(或允许用户共享主题)。
结论
自定义属性让我们能够轻松对网站进行彻底的更改。这使得它们成为实现主题定制的绝佳工具,无论是自动检测用户的主题偏好,prefers-color-scheme
还是允许他们选择(并可能修改)自己的主题。