Hugo 如何让图片在暗色主题下反色 - 自写主题
2021年8月28日 - 1002 字

本文探讨的是图片在亮色、暗色主题下的显示问题,里面有一些图片示例,请读者们手动调节本站的主题来测试它们的显示效果. 调节按钮在左边栏的右上角,手机等小屏幕请点击左上角的汉堡按钮呼出左边栏.

问题

有些图片是白底黑字,在暗色主题下刺眼:

白底黑字的示例图
◉ 图. 白底黑字的示例图

有些图片是透明背景黑字,在暗色主题下看不清:

透明背景黑字的示例图
◉ 图. 透明背景黑字的示例图

以上这两种情况都需要在读者选择暗色主题的时候进行反色处理.

处理思路

颜色的反转使用 CSS 的滤镜(filters)技术即可,比如在如下代码中,.normal 是正常的颜色,.inverted 是反转的颜色.

1
2
3
4
5
6
7
.normal {
	filter: invert(0%);
}

.inverted {
	filter: invert(100%);
}

我们可以把上面的代码套进 CSS 变量中,和两套主题的变量放在一起. 然后在 Hugo 的模板中更改处理图片用的 render hooks,给图片加上适当的样式即可.

其中暗色主题的切换参考的是这篇文章,简单来说,就是在读者切换成暗色主题时给整个 <html> 容器加上一个表示暗色主题的类名(.classList.add("dark")),读者切换成亮色主题时将这个类名去掉(.classList.remove("dark")),然后在 CSS 中针对是否有那个暗色主题的类名,把不同的值定义给同一个变量,而在指定 HTML 元素的样式时直接使用那个变量即可. 详见下面的代码.

完整代码

首先是 HTML 示例代码,在整个 <html> 容器上定义一个类:

1
2
3
4
5
<html class="theme-container">
    <body>
        <!--Something…-->
    </body>
</html>

然后在 CSS 中对这个容器是否有暗色主题类名 .dark 分别定义变量 --c-img-filter

1
2
3
4
5
6
.theme-container{
    --c-img-filter: invert(0%);
}
.theme-container.dark{
    --c-img-filter: invert(100%);
}

最后处理 Hugo 模板:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!-- layouts/_default/_markup/render-image.html -->

{{ $url := .Destination | safeURL }}
<figure>
    <img src="{{ $url }}"
        {{ $file_name_array := split $url "." }}
        {{ $file_name_len := len $file_name_array }}
        {{ if eq (index $file_name_array (sub $file_name_len 2)) "i" }}
            style="filter: var(--c-img-filter);"
        {{ end }}
    >
</figure>

这里没有贸然对所有的图片都加上 style="filter: var(--c-img-filter);",而是先对文件名进行分析,最后达到的效果是:以 .i.{png|jpg|gif|jpeg|webp|…} 作为文件名后缀的图片会在选择暗色主题时进行反色处理,而没有 .i 这个文件名修饰的图片则永远保持原样. 例如:

  • 这张图片文件名为 lorem.i.jpg,亮色模式下白底黑字、暗色模式下黑底白字

lorem.i.jpg
◉ 图. lorem.i.jpg


  • 这张图片文件名为 lorem.i.png,亮色模式下透明底黑字、暗色模式下透明底白字

lorem.i.png
◉ 图. lorem.i.png


  • 这张图片文件名为 cat.jpg,亮色模式与暗色模式下都是正常的颜色

cat.jpg
◉ 图. cat.jpg


友情链接(该栏目下的其他文章)

  1. 第 1 期:Hugo 静态博客建站记 - 自写主题
  2. 第 2 期:博客记录书影音——Hugo 的 Data Templates - 自写主题
  3. 第 3 期:如何让静态网站的暗色主题换页不闪烁 - 自写主题
  4. 第 4 期:Hugo 如何让图片在暗色主题下反色 - 自写主题(就是这篇!)