S

计算机科学中最困难的事:居中

·Shinji

原版: 英文 翻译: 日语 俄语

原文发表于2024年04月16日。

总而言之:我们作为文明的一份子,却忘记了如何居中。

我的意思是,我们知道 如 • 何 • 居中,这不能更简单了:

display: flex;
 
justify-content: center; /* Horizontal centering */
 
align-items: center; /* Vertical centering */

(不要问我为什么需要使用四个单词来解决明明用一个单词 horizontal/vertical 就能够解决的问题, 已 • 经 • 比 • 之 • 前 • 好 • 多 • 了 • )

当然你也可以使用 grid:

display: grid;
 
justify-items: center; /* Horizontal centering */
 
align-items: center; /* Vertical centering */

(同样不要问我为什么 justify-content 变成了 justify-items

如果你想深入了解这些,很容易发现:

您猜怎么着,甚至 ChatGPT 都知道如何居中

好吧,这也许存在问题,但至少它知道。

我想说的是:所有人都知道如何居中。虽然比较唠叨:如果你不会,尽管去查。

然而,在实际应用中并没有使用以上所述的方法,我们发现:

或者这个:

甚至这个:

因此,在掌握的知识和实际应用中总是差了点什么。

理论上来说理论应与实际相同,但不幸的是,我们没有生活在理论中。

所以发生了什么?让我们来找找原因。

字体

字体是最大的“罪魁祸首”之一。在实际中随处可见对齐不良的文本,让我来展示一下:

苹果没做到:

微软没做到:

GitHub 没做到:

Valve 没做到:

Slack 没做到:

Telegram 没做到:

Google 地图没做到:

说真的我能够提供无尽的像这样没有完全对齐的按钮:

我想你已经明白了:大大小小的公司数不胜数,不管是专注于原生应用的公司还是互联网公司,没有一家能幸免于文本居中的问题。

行高

如果解决了字体的问题,那么完美居中的下一个障碍是行高。

行高是……非常复杂。帮助你了解行高的经典文章是 Vincent De Oliveira 的 Deep dive CSS: font metrics, line-height and vertical-align

让我们来看看实际上怎么样:

Slack:

Notion:

Airbnb:

YouTube:

将不同容器中的两个东西对齐几乎是不可能的:

尽管很多人都尝试过:

但成功的人并不多:

CSS 可能会妨碍对齐(不同的控件具有不同的默认值,必须在开始对齐之前重置这些默认值):

没有简单的解决方案,只能因地制宜,撸起袖子加油干。

图标

图标就像与文字放在一起的小矩形。因此,字体和行高引起的所有问题在这里都会再次出现。将图标与文本对齐是一项出了名的难事。

Atom:

以前大家所熟知的 Twitter:

iOS:

Mozilla:

YouTube:

有些图标高于文字:

有些图标低于文字:

有些时候两者都没对齐:

有些图标是最原始的样子:

有些却拥有样式:

感谢 @bee 提供这张图片

有时,人们会创造性的达到完美的对齐效果:

但总的来说,这是非常令人绝望的:

问题是,CSS 也帮不了我们。 vertical-align 有 13 种可能的值,但没有一种能让图标以有意义的方式对齐:

text-align: middle 看起来快成了,但它是按 x 高度对齐,而不是按大写字高对齐,这看起来仍然不平衡:

这就是人们爱死网页前端的原因:无时不刻的接受挑战。

图标字体

对齐矩形相对容易。对齐文本则很难。已知图标是矩形。那么,如果我们将图标放入字体文件中呢?

现在我们不能对齐任何东西了:

我们也无法设置图标大小!在上面的示例中,所有图标的字体大小和行高都是一样的。正如你所看到的,所有图标的大小都不一样,填充大小也不一样,而且都没有正确的对齐。

尽管有不少缺点,公司们还是在把图标字体推广到所有地方,这导致了:

![](https://xhvtonnrlgsxoqbvmxbo.supabase.co/storage/v1/object/public/Shinji/upload/IMG-20250501220719659.webp]] macOS 10.14 → macOS 10.)

请注意,操作符不再垂直对齐,也变得模糊不清。这都是因为切换到了图标字体。

苹果公司如此执着于图标字体,甚至毁掉了 QuickTime 录制按钮:

仔细看看:

是的,直到现在它还是这个样子。计算器也是如此。

但他们远非唯一。

一:

二:

三:

四:

五:

六:

七:

与文本相同,没有完全对齐的图标也是无限的。

技术问题

不仅程序员会遇到技术问题,设计师也会:

当前版本 / 我的修复后的版本

图标的问题在于,有时你必须考虑到图标的形状,这样才能让东西看起来更美观:

不良的居中 / 良好的居中

三角形非常的棘手:

有时过于偏左:

有时过于偏右:

甚至可能太高(行高问题又出现了):

横向居中

你也许会认为只有竖向居中很困难。错了!横向一样困难:

我觉得这只是人们太粗心了:

唉,来就来吧。

这会是一个深思熟虑的决定吗?

我不知道。图标会受到影响:

当然文本也会:

对设计师而言可以采取的方案

所以,什么 是 • 问题?

一切从字体开始。现在,文本块的边界是这样的:

问题是,它也可以是这样的:

或者这样的:

现在,如果你尝试将文本框居中,那么会发生什么情况呢?

文字会出现偏移!即使文本框完全居中。

但是,尽管字体度量 可 • 以 • 不平衡,但是这不意味着它们看起来不平衡。到底发生了什么?

实际上, 大 • 部 • 分 • 流行字体的度量都是不平衡的。许多字体 非 • 常 • 明显:

百分比为大写字高的百分比

10% 并不是一个小数字。在字体大小为 13 的情况下,这可是整整一个像素!如果在两倍 2 倍缩放的情况下,将会是两个像素!这很容易察觉。

基本上,Segoe UI 就是 Windows 上的 Github 看起来像这样的原因:

解决方案很简单:使用紧凑的文本框来居中就能解决。

如果你正在使用 Figma,它已经能够做到了(尽管不是默认的):

对字体设计师而言可以采取的方案

如果你是字体设计师,请将度量值设计为 ascender − cap-height = descender 以方便大家使用:

图示解决方法:

重点!你不需要 真 • 的 • 让 ascenders/descenders 撑满边界。如图所示,上部远未被充分利用。只需使数值匹配即可。

无论是网页还是本地字体,为了避免麻烦,请选择已经遵循这一规则的字体。SF Pro Text、Inter 和 Martian Mono 似乎已经遵循了这一规则,因此无需额外的努力就能完美居中。

阅读 Font size is useless; let’s fix it 以了解更多。

对网页开发者而言可以采取的方案

从开发人员的角度来看,这就比较棘手了。

首先要了解的是,你需要知道要使用哪种字体。遗憾的是,如果你打算替换字体,这就行不通了。

我们将使用 IBM Plex Sans 字体,这种字体在本页面上使用过。IBM Plex Sans 具有以下度量:

当你设置 font-size 时,设置的是 UPM(也等于 1em )。但是,文本块实际占用的空间是 ascenderdescender 之间的空间。

通过简单的计算,我们可以加上额外的 padding-bottom: 0.052em

它像这样工作:

在 CSS 中:

Andy

你可以从 https://opentype.js.org/font-inspector.html 获得你所使用的字体的度量(ascender, descender, sCapHeight)。

既然我们已经解决了这个问题,那么对齐图标也就不难了。你可以设置 vertical-align: baseline ,然后将它们向下移动 (iconHeight - capHeight) /2

不幸的是,这需要你同时知道字体度量和图标大小。不过,至少它还能用:

Andy

再次选择上面的文字,看看浏览器的边界框与正确位置有多大的差异。

对图标字体可以采取的方案

不 • 要 • 使 • 用 • 图 • 标 • 字 • 体 • 。

使用正常的图片格式。有尺寸的那种,是那种有宽度和高度的。

在这里,我为你画了一张图,帮助你做出决定:

看看苹果是多么努力地把复选标记放在矩形内,然后把矩形放在文本标签旁边:

然后失败了!

没有比对齐两个矩形更容易的事了。同时,最难的莫过于对齐周围有任意空白空间的文本。

它们不可能做到的。

可用的视觉补偿

我们,开发人员,只能用数学方法来对齐完美的矩形。因此,对于任何需要手动补偿的图标,请将其包入一个足够大的矩形中,并在视觉上平衡图标内部:

所有人都应该做的

集中注意力并仔细的处理问题。不佳的居中对齐会毁了原本不错的 UI:

但正确对齐的文本可以让 UI 熠熠生辉:

尽管这很难;尽管工具会带来不便;尽管你必须寻找解决方案。我相信,只要我们戮力同心,就一定能找到办法,把一个长方形放在另一个长方形里,而不弄乱任何东西。

就我而言,我希望生活在一个充满美丽而均衡的 UI 世界里。我相信你们也是如此。

这一切都是值得的。

特别提名

没有这个老伙计我们的文章是不完美的:

!()[https://xhvtonnrlgsxoqbvmxbo.supabase.co/storage/v1/object/public/Shinji/upload/spinner.mp4]

细心!千万不要让东西变成这样!