Joye Personal Blog

Back

排版 numberstypographyalignment

会变的数字,用等宽数字

多数字体里“1”比“0”窄,跳动的计时器会左右晃,表格里的金额也对不齐。会变、要比较的数字,换成等宽数字。

来源 ↗
views

我常在下载页面上看到这样的进度:右侧那串“已下载 37.2 MB”一直在轻轻发抖,数字本身没错,可每涨一下,整串文字就往左或往右挪一点点。问题不在布局,而是字体里每个数字本来就不一样宽。换成等宽数字,抖动就没了。

盯住秒表数字的左边缘,再看账单的小数点。计时中
✕ 字体默认的比例数字
秒表00:56.80

最近一秒,左边缘来回移动了 0 px

lab-assets.zip40.4 / 128.0 MB
本月账单金额
域名续费¥ 111.11
对象存储¥ 1,048.00
CDN 流量¥ 980.80
云服务器¥ 1,111.11
合计¥ 3,251.02

“1”比“0”窄一大截。数字每跳一下,整串的宽度就变一次,右对齐的左边缘跟着来回晃;账单里的小数点也偏离了虚线。

✓ 等宽数字
秒表00:56.80

最近一秒,左边缘来回移动了 0 px

lab-assets.zip40.4 / 128.0 MB
本月账单金额
域名续费¥ 111.11
对象存储¥ 1,048.00
CDN 流量¥ 980.80
云服务器¥ 1,111.11
合计¥ 3,251.02

同一个字体,只是让每个数字占一样宽。秒表只有数字在变,位置纹丝不动;账单的小数点和千分位自然排成一条竖线。

✓ 再进一步:让数字滚过去
等宽数字 · 直接换¥128.00
等宽数字 · NumberFlow 滚动¥128.00

等宽数字解决了“抖”,数字变化本身还是一下跳过去的。价格、余额、计数这种值得被注意到的变化,可以让每一位像拨号盘一样滚到新值:变了多少、往哪个方向变,一眼就看得到。右边用的是 NumberFlow,一个很小的开源组件,系统开启减少动态效果时会自动不滚。

01多数字体默认用比例数字,“1”窄、“0”宽,放在句子里更匀称。可一旦数字会跳,宽度就跟着跳。
02会变的数字(计时、进度、价格、计数)和要上下比较的数字(表格、账单、排行),都改用等宽数字。
03通常不用换字体:大多数现代字体同时带着两套数字,打开一个开关就行。左右两栏用的就是同一个字体。
左右两栏是同一个字体、同一份数据。盯住秒表的左边缘,下方色带是它最近一秒到过的范围。

为什么这样更好#

  • 比例数字是为句子设计的。字体默认让“1”窄一些、“0”宽一些,夹在文字里读起来更匀称。可放进计时器、计数器里,数字每变一次,整串的宽度也跟着变。
  • 右对齐会把宽度变化变成晃动。右端固定,宽度一变,左边缘就来回跳。眼睛会被这点抖动一直吸引过去,注意力反而离开了数字本身。
  • 等宽数字只让内容变,不让位置变。每一位数字占一样宽,秒表从 09 走到 11,字形换了,位置没动。读的人看到的是“数在涨”,而不是“文字在抖”。
  • 表格里的数字要能竖着比。等宽数字让相同位数的数字更容易对齐;若要让小数点也排成一列,还需统一整数位宽或单独按小数点对齐。
  • 通常不用换字体。大多数现代字体同时带着两套数字,只是默认用比例那一套。打开等宽数字这个开关就够了,不必为了数字专门换一套等宽字体。

我的习惯是:只要一个数字会在用户眼前变化,或者会和上下几行放在一起比较,就默认用等宽数字。

再进一步:让数字滚过去#

等宽数字解决的是“抖”,但数字变化本身仍然是一下跳过去的。对价格、余额、点赞数这种值得被注意到的变化,我更喜欢让每一位像拨号盘一样滚到新值:涨了还是跌了、变了多少,不用盯着前后两个数去比。

demo 最下面那组用的是 NumberFlow ↗,Maxwell Barvian 做的开源数字动画组件。它把格式化交给浏览器自带的数字格式(货币、千分位、单位都能用),无需额外的格式化库;使用 NumberFlow 本身仍需安装对应的组件包。系统开启减少动态效果时会自动不滚,React、Vue、Svelte 都有对应的版本。想给自己的页面加上这种效果,把这个链接丢给你的 Agent 就够了。

什么时候不该用#

  • 正文段落里的数字,比如“去年读了 11 本书”。它不会变,也不和谁对齐,比例数字读起来更自然。
  • 大号的展示数字,比如封面上的年份、营销页上的单个统计数字。这时字形之间的间距比对齐更重要,等宽数字里“1”两边会显得空。
  • 如果字体本身没有等宽数字这套字形,打开开关也不会生效。用之前先在页面上看一眼实际效果。
  • 滚动数字只给真正值得注意的变化。每帧都在跳的秒表、下载进度用滚动反而更乱,等宽数字就够了。

出处#

Vercel 的 Web Interface Guidelines ↗ 在 Content 一节里专门写了一条:需要比较的数字用等宽数字,或者直接用等宽字体。两套数字的定义可以参考 MDN 的 font-variant-numeric ↗。滚动数字来自 NumberFlow ↗。