这篇博客文章是关于我在Laravel的README文件中对我们开源库的logo SVG引入深色模式的(失败)尝试。我觉得分享我在这个尝试中的经验和目前阻碍我们引入这些模式的因素会很有趣。
序言
我们所有存储库中的README文件几乎都有一个包含项目标志和一些徽章的头部:
这些徽章特色是具有图标和深色文字的透明SVG标志,它通过img
元素加载
<p align="center">
<img src="/art/logo.svg" alt="Logo Laravel Cashier Stripe">
</p>
这种情况一直工作得很好,因为GitHub的README文件总是使用白色背景和深色文本。但是,直到他们引入了深色模式为止。这意味着用户现在可以切换到GitHub的新深色主题。但是,由于这个变更,在深色模式启用时,我们的标志看起来像下面这样:
我想知道是否可以修复这个问题。归根结底,SVG由标签组成,你已经在它们中使用基本的CSS和像style
这样的属性(虽然不是所有都受支持)。因此,我开始了尝试去尝试根据深色模式是否启用来切换字体颜色。但这并没有按我想象的进行。
尝试#1:媒体查询
在CSS中检测深色模式最基本的方式是通过媒体查询。下面是我们使用的SVG标志源代码的简化版本:
<svg xmlns="http://www.w3.org/2000/svg" width="360" height="64" viewBox="0 0 360 64">
<!-- Icon Specific paths and definition tags. -->
<path fill="#2E2E2E" d="..."/>
</svg>
文档从svg
标签开始,该标签包含xmlns
定义,以及width
和height
属性以及viewBox
。在SVG图标内部,有特定的路径和定义标签构成了标志的图标。最后,我们还有塑造字母的路径。它具有一个fill
属性,表示字母应该用哪种实心颜色填充。
为了更简化这篇文章中的示例,我将省略更多的图标部分,并继续以下基本示例。
<svg>
<path fill="#2E2E2E" d="..."/>
</svg>
现在,我第一次尝试引入媒体查询。我想,如果网页检测到暗色模式被启用,那么GitHub页面也会进入暗色模式。所以我最终写下了以下内容
<svg>
<style>
.letters { fill: #2E2E2E; }
@media (prefers-color-scheme: dark) {
.letters { fill: #ffffff; }
}
</style>
<path class="letters" d="..."/>
</svg>
这出乎意料地有效!当我将它推广到仓库时,我可以看到根据系统的暗色模式状态,字母的颜色会变为白色或黑色。不幸的是,这只能在Chrome和Firefox中工作,我无法在Safari中实现它,这是我发现的。我感谢Amelia Bellamy-Royds,因为她向我解释说这可能是浏览器的一个错误()。但这对我来说是超出我探究能力的。在最坏的情况下,Safari的用户将无法欣赏新的暗色模式标志。
我开始将这个功能推广到我们的仓库时,社区成员Bruno Gaspar告知我存在一个我尚未考虑过的用例。事实证明,我已经忘记了如果有人明确地将GitHub主题设置为暗色或亮色,媒体查询仍然会根据系统的状态进行切换。这导致当用户的系统处于暗色模式但其GitHub主题被明确设置为亮色时,标志看起来像下面这样
尝试#2:数据属性
这是一个明显的用例,但我确实错过了。但我告诉自己:“接受挑战”,并开始找出这个问题的答案。
结果表明,GitHub通过在其html
元素上设置data attributes
来定义其状态。这很有用,因为这样我可以检查系统的状态和网页的状态来切换字母颜色。
<!DOCTYPE html>
<html
lang="en"
data-color-mode="auto"
data-light-theme="light"
data-dark-theme="dark_dimmed"
>
因此,我们看到GitHub定义了以下属性:data-color-mode
、data-light-theme
和data-dark-theme
。对我们最有用的是一个data-color-mode
,因为其他两个仅定义用户对亮色或暗色模式的特定颜色主题的偏好。data-color-mode
具有以下三个值:light
、dark
和auto
,这是用户为切换暗色模式设置的偏好。
好了,现在我已经有了这些信息,我按照以下方式修改了SVG标志
<svg>
<style>
.letters { fill: #2E2E2E; }
@media (prefers-color-scheme: dark) {
html[data-color-mode="auto"] .letters {
fill: #ffffff;
}
}
html[data-color-mode="dark"] .letters, {
fill: #ffffff;
}
</style>
<path class="letters" d="..."/>
</svg>
让我们解释一下以上选择的样式的原因。首先,默认情况下,字母保留亮色模式下的原始外观,暗色字母。然后,我们会检查系统是否在暗色模式下。如果是的话,并且用户的颜色主题会自动切换,我们知道GitHub也将处于暗色模式。所以我们应用白色字母。第三,如果GitHub明确处于暗色模式,我们始终应用白色字母。这将覆盖我们需要的所有用例。
我很高兴找到了一个解决方案,并且GitHub使得检测其活动主题类型变得非常容易,所以我很积极地提交了一个标志并刷新了我的浏览器。但是……什么也没有发生。更糟糕的是,之前的中断媒体查询似乎不再起作用,字母仍然很暗。发生了什么事?
最终,经过一番研究,发现通过《code`img`元素引用的SVG不受父DOM元素的限制。因此,前面的中断媒体查询已经损坏,属性不起作用,因为SVG根本无法读取这些属性。
这真是一件令人沮丧的事情。更糟糕的是,GitHub不渲染其readme文件中的内联SVG。
结论
我最后尝试的是找到一种在这个暗色模式和亮色模式下都看起来不错的通用字母颜色。但总是太暗或太亮。我尝试采用Laravel在Laravel的 `laravel/laravel
仓库`中使用的颜色SVG标志,但这与其他库的图标不符。
所以最终我不得不放弃,将标志恢复到原始状态。然而,我从中学到了很多,并想与大家分享。谁知道呢,这可能会对某个人有所帮助。
如果您觉得这篇文章有用,或者您知道些不同的想法,请一定告诉我 在Twitter上并关注我,如果您想了解我接下来的动向。感谢阅读!
joedixon, globalindex 赞同了这篇文章