mikexxz
全部文章

把 Apple HIG 翻译成 Web 的 design tokens

一块半白半黑的玻璃质感苹果形物体,字号阶梯与彩色色块从中飞出,下方有一条弹簧曲线。

Apple 的 Human Interface Guidelines 是为原生 app 写的,但其中的很多原则——层级清晰、内容优先、尊重用户的系统设置——在 Web 上一样成立。难点在于把 pt、Dynamic Type、语义色这些概念翻译成 CSS。

字号:Dynamic Type → rem

iOS 的默认字号以 pt 为单位,在 Web 上直接除以 16 换算成 rem:

样式 iOS (pt) Web (rem)
Large Title 34 2.125
Title 1 28 1.75
Title 2 22 1.375
Body 17 1.0625
Footnote 13 0.8125

用 rem 而不是 px 的好处是:用户在浏览器里调大默认字号时,整个站点会等比放大。这差不多就是 Web 版的 Dynamic Type。

iOS Dynamic Type 字号阶梯
iOS Dynamic Type 的九级默认字号,以及换算后的 rem 值。

语义色

组件里不写 #000,而是写 var(--color-label)。深色模式只需要在一个地方重新定义变量:

:root {
  --color-label: #000000;
  --color-background: #ffffff;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-label: #ffffff;
    --color-background: #000000;
  }
}

一个和 HIG 冲突的地方

iOS 的 secondaryLabel 在白底上的对比度只有 3.4:1 左右,达不到 WCAG AA 要求的 4.5:1。原生 app 可以靠系统的“增强对比度”选项兜底,网页没有这个开关,所以这里把它的透明度从 0.6 提到了 0.75。

同理,#007AFF 作为正文链接颜色也只有约 4.0:1,链接文字单独用了更深一点的 #0066CC。

动效:弹簧曲线

CSS 的 linear() 函数可以用一串采样点描述任意曲线,于是可以把真实的阻尼弹簧方程采样后写进 CSS,而不是用 cubic-bezier 去近似。

弹簧曲线与 ease-out 曲线对比
阻尼比约 0.8 的弹簧会略微越过终点再回落,ease-out 则平滑地停住。

弹簧在终点附近有约 1.4% 的回弹,幅度很小,但正是这一点让按压反馈显得“有弹性”。

评论

删除这条评论?

评论内容会被清除,无法恢复。