Translating Apple's HIG into Web Design Tokens

This post was machine-translated from Chinese. Read the original
Apple's Human Interface Guidelines were written for native apps, but many of their principles (clear hierarchy, content first, respect for the user's system settings) hold just as well on the Web. The hard part is translating concepts like pt, Dynamic Type, and semantic colors into CSS.
Font Size: Dynamic Type → rem
iOS default font sizes are specified in pt. On the Web, divide by 16 to convert them to rem:
| Style | 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 |
The advantage of rem over px is that when users increase the default font size in their browser, the whole site scales up proportionally. That is more or less the Web version of Dynamic Type.
Semantic Colors
Components don't use #000; they use var(--color-label). Dark mode then only needs to redefine the variables in one place:
:root {
--color-label: #000000;
--color-background: #ffffff;
}
@media (prefers-color-scheme: dark) {
:root {
--color-label: #ffffff;
--color-background: #000000;
}
}
Where This Conflicts with the HIG
On a white background, iOS's secondaryLabel has a contrast ratio of only about 3.4:1, short of the 4.5:1 required by WCAG AA. Native apps can fall back on the system's "Increase Contrast" option, but the Web has no such switch, so here I raised its opacity from 0.6 to 0.75.
Likewise, #007AFF as a body link color reaches only about 4.0:1, so link text uses a slightly darker #0066CC instead.
Motion: Spring Curves
CSS's linear() function can describe an arbitrary curve with a series of sample points. That means we can sample a real damped spring equation and write the result into CSS, instead of approximating it with cubic-bezier.
The spring overshoots by about 1.4% near the end point. That is a very small amount, but it is exactly what makes press feedback feel "springy".
Comments