稳定的接口是对接外部系统的基石,但是不当的假定不应该升格成为接口,无论这种假定看起来有多理所应当。
最近随着无障碍访问改善工作的进行,我发现这个主题里面包含的问题还是挺多的。其中有一些可能是因为当时转 11ty 时没有完整地实现整个页面的行为,比如最近才修好的暗色主题没有正确应用情况;另一些则是主题本身就带着的实现缺陷,比如图片灯箱组件没有正确的焦点。
我注意到这个主题有对语义化 HTML 的理解和规范不一致的情况。一开始我计划通过 custom.css 结合尽可能小的模板修改去一点点修掉「不符合认知」的部分,但是修着修着就发现补丁是打不完的,而且经常会按下葫芦浮起瓢。由于原先主题的 CSS 对于 HTML 的嵌套顺序有非常特殊的要求,修改 HTML 元素意味着大批量地修改 CSS, 而且通常修改完成之后总是看起来和原始设计差一点。要命的是,差这一点所带来的「不匀称」的感觉非常明显。
在实现 IndieWeb 相关的各种小工具的时候,我发现要对模板做的修改就更多了:引入 Webmention 并不仅仅是引入 Webmention 本身,它也意味着引入一堆 IndieWeb 给出的其他怪东西,比如你需要正确地实现 microformats2 才能「正确」地给其他站点发送 Webmention.
事已至此,我想或许我也可以行使一下我的主观能动性,再来一场酣畅淋漓的狂野 Web 开发!
不破不立
首先,移除所有的样式和脚本,使得站点退化到只有纯 HTML 结构的状态。去除了样式和交互之后,就更容易看出哪些 HTML 构造是有问题的,以便后续进行重构。
去伪存真
先修复文章列表页面的 HTML 语义问题——原有的列表页依赖于 <article> 和 <main> 元素的组合,使得列表的每个条目都包含了 <main> 元素。这个在 HTML 语义上实际是不允许的[1]。自然,这些问题组合需要被移除重写。
同样的,冗余的 <div> 和 <section> 嵌套也可以一并删除。大部分的 class 属性也可以尽数移除。我尽可能地将原来层层嵌套的文本上移又上移——得益于现代浏览器的特性,我已经可以不再用 <div> 套 <div> 的方式来做排版了;同样,我也不需要再用一个单独的控件来切换亮色和暗色主题了:@media (prefers-color-scheme) 在绝大多数浏览器上都已经有了很好的支持[2],所以这个站点可以直接随着你的浏览器全局设置甚至系统的全局设置自动调整色盘。
去除这些冗余的元素,并换用带有语义的 HTML 元素,很大程度上减少了无障碍访问需要额外做的工作(比如给各种 <div> 或者 <section> 指定 role 属性,或者给一些纯粹的视觉装饰元素指定 aria-hidden 属性)。同时,由于去掉了亮暗切换控件,Tab 键顺序也不再需要手动调整了。
每个页面都由三个主要部分组成:头、身、尾,对应 <header>, <main>, <footer>. 头部主要是页面大标题、导航栏,以及文档的必要元信息;身体自然是文章列表或者文章正文;尾巴则是底部导航、版权信息和合规性小字,组织起来大概就是:
<!DOCTYPE html>
<head>
<!-- 从略 -->
</head>
<body>
<header>
<h1>大标题</h1>
<nav>
<ul>
<li><a href="#main" class="sr-only">跳到内容</a></li>
<li><a>顶部导航</a></li>
</ul>
</nav>
<section>
<span>Yours Truly</span>
<time>2026-12-31</time>
</section>
</header>
<main>
<article id="main">
<p>正文</p>
</article>
</main>
<footer>
<nav>
<ul>
<li>底部导航</li>
</ul>
</nav>
<section>
<p>© 2026</p>
</section>
</footer>
</body>
<!-- 实际页面的实现可能和上述结构有所差异 -->
现在,我们有了一个良好标记的文档,接下来就是应用一些样式了。
因为我需要手写模板和 CSS 样式,所以核心框架就是:在能够满足「匀称」的前提下,尽可能少做一些 <div> 套 <div> 的动作、少引入各种样式,并且尽可能少写几行 CSS. 同时,生成的页面结果需要至少能过 Nu HTML Checker 而不报错。
大道至简
从整体的观感上,我想模拟纸张和卡片的质感,但是我实在是不想手写整套老的 Material Design 的那堆效果,毕竟我想要的是很简单的东西:简单的白纸、简单的文字、干净而稳定的呈现。它不会有复杂的动画效果,也不考虑任何元素间的交互。换句话说,它应当是一本纸质笔记本的数字化呈现。
自然的,顶层容器就是笔记本上的纸张啦。我琢磨了一小会「如何让背景看起来像纸」,最终觉得一比一地还原纸张的样貌的工作量有点超预算:因为无论是通过加载一张图片作为背景拼贴,还是通过脚本动态地计算纸张的材质,都要花费不少功夫(和网络带宽)。虽然尝试通过代码绘制一个带有反射率各向异性的材质是一个不错的计算机图形学练习,但我实在是写不动了。
不过,我们并不需要真的去一比一地模拟纸张。我们只需要「提示」这是一个「有层级」的部件就足够了。Web 给我们用于提示层级的最直接的手段就是边框投阴影(笑)。
这样看起来就足够了。同时,为了体现出纸张硬质的质感,我选择不给容器加圆角。不过内联代码的边框作为文字的一部分,是可以更圆润的。
虽然名为网页的稿纸本身并没有打格子,我还是决定正文的最大宽度是四十列汉字,对应等宽西文字体的 80 列宽。我一直觉得 80 列宽是一种非常有趣的巧合。尽管显示器的宽度自 IBM 终端机时代已经拓宽了不少,但是人眼一行能扫描的宽度却并没有随之增加。在 12pt 的字号下,80 列等宽字符几乎刚好是最大阅读宽度。
以人为本
无障碍访问自然是此次设计的重点。使用语义化的 HTML 配合适当的 aria-label 和 aria-labelledby 可以给屏幕阅读器提供各个区域的类型(比如这个部分是正文还是导航栏),以便用户快速地在区域间跳转。当 VoiceOver 焦点移动到一个看起来没有标记的框框上之后却能够正确地说出「文章标签,补充;你当前在网页内容的补充上」的时候,我确实有一股莫名的欣慰感上头。
对于评论区这种会有动态内容加载的区域,可以指定 aria-live 属性。这样,当这个元素内部有 DOM 变更时,屏幕阅读器就会按要求向用户播报。
在挑选站点颜色的时候,我按照习惯选择了 DawnBringer 32 色盘,并遵照 WebAIM 的对比度要求调整了各个文字控件的色彩搭配。当然,部分特殊结构的色彩选择可能仍然会出现对比度不足的情况(比如对话窗格的系统文字),这个只能先无奈妥协了,毕竟它需要遵循原始文稿定下的设计。
同时,也需要强调一下:深色主题也是无障碍访问的一部分。尽管我个人更偏好使用浅色主题,深色主题也是不能落下的。同样的,深色主题也要根据 WebAIM 的要求调整文字对比度,以及调整其他视觉元素的颜色,避免出现在深色模式下用浅色控件的情况。
因为这回我对于页面样式有了全权控制,所以代码块现在也增加了颜色自适应能力——终于不用在浅色背景上糊一个深色代码块了!
无障碍访问自然是需要持久地改善的,随着 WAVE 工具报告 0 错误之后,我终于算是挣得了「改善」而不是「修复」的资格了。
有了更简洁的 HTML 结构,之后我们引入 IndieWeb 所需要的完整的标记架构就会更容易一些。目前这套主题已经开始实验性地包括一些基本的 microformats2 的语义标记,至少 Firefox 的阅读器视图中已经可以识别诸如作者名之类的信息了。
后续的工作自然包括通过工具验证页面的结构是否正常以及提供更多的必要信息,以完整地支持 Webmention 所需要提供的内容。
尾声
虽然站点大小并不是工作的重点,不过甩掉了 jQuery 这个大头之后,站点总共需要加载的样式和脚本下降到了 85kB+. 我所编写的样式和脚本由于没有过最小化,每个也有 5kB~12kB, 不过这个通过 Gzip 压缩后应该并不构成问题。
当然,目前这套结构还是有一些缺憾的,比如包含内联代码的行高和普通文字的行高不一样,所以一些情况下看起来会有些奇怪;以及一些中文标点的排版仍然有改进的空间,比如冒号和引号、括号和逗号等之间应考虑共享空白空间(各自占半个字)。或许这套主题应该加一些交互的小动效,现在看起来实在是有些呆板了。
而且,毕竟是重构,这套主题里应该还会有一些我没有注意到的小细节没能正确地实现。尽管我在实现这套主题的时候翻看了之前已经发布的全部文章并测试了评论区的功能,但我并不会惊讶某天我又会在查阅历史文章时发现一个看起来十分别扭的元素。只能希望未来的我不会痛骂今天的我的小小疏忽吧 \blep{}。
Tokin 兄,谢谢你的 Adams 主题,我真的很喜欢!感谢六年的陪伴,再见。
后日谈:你知道你的站点在不同的浏览器下看起来是不一样的么?
我知道,因为我在设计整套主题的时候都在一个开了浏览器指纹对抗的 Firefox 上进行,等我调整完了之后出于纯粹的好奇,用 Safari 打开了页面,发现页面渲染的结果略微略微地有那么点不同。好在看起来还行,不至于到不匀称的地步。
不过我认为这并不是一个大问题,因为这个现象来自一个刻意的选择:
因为我在写 CSS 的时候,选择了使用 1rem 而不是 16px 作为基本尺寸,所以如果浏览器选中的字体有差别的话,整个文档渲染出来的结果就是不一样的。
这其实也是无障碍设计的一部分。如果有人需要默认字号更大一些的话,那么这套框架也不会产生行压行的尴尬情景;如果有人喜欢正文使用他们自己指定的字体的话(比如辅助失读症人士阅读的字体),这套排版规则也会跟着自动调整。












