本文最初发布于 Niki 的个人博客。
对于居中显示,我们都知道该怎么做,它是如此得简单:
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
(不要问为什么你需要记住四个单词而不是 horizontal 和 vertical 两个单词,这已经比以前好了)
如果你愿意,你也可以使用网格:
display: grid;
justify-items: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
(不要问为什么 justify-content 变成了 justify-items)
如果你想学的话,我们可以从下面这个基本原理入手:
甚至是 ChatGPT 也知道如何把一个东西居中:
好吧,也许有点慢,但最终可以做到。
我要说的是:每个人都知道如何把某个东西居中。小事一桩。如果你不知道怎么做,也有现成的知识供你查阅。
然而,如果我们查看下实际的应用程序就会发现,它们并没有使用这些方法。我们看到:
或者:
甚至是:
显然,在知识和知识的应用之间,有些东西丢了。
理论上,理论和实践之间并没有什么不同。遗憾的是,我们生活在实践中。
让我们看一下到底发生了什么。
字 体
字体是罪魁祸首之一。未对齐的文本随处可见。让我们看一些例子。
苹果没做到:
微软没做到:
GitHub 没做到:
Valve 没做到:
Slack 没做到:
Telegram 没做到:
谷歌地图没做到:
说实话,像这样糟糕的按钮对齐,我不用找就能举出无数的例子:
我想你已经明白了。许多公司,无论大小,都未能免于文本居中的问题。
行 高
除了字体参数,下一个影响完美居中的问题是行高。
行高是一个复杂的话题。在这方面,Vincent De Oliveira 曾写过一篇经典的文章“深入理解 CSS:字体参数、行高和垂直对齐”。
下面是一些实际的例子。
Slack:
Notion:
Airbnb:
YouTube:
对齐两个位于不同容器中的东西几乎是不可能的:
虽然许多人尝试过:
但没有多少人成功:
CSS 可能是个障碍(不同的控件有不同的默认值,你必须在尝试对齐之前取消它们):
没什么简单的办法,只能对照规范一点点来。
图 标
图标就像是与文本排成一行的小矩形。因此,所有由文本和行高引起的问题这里也都存在。众所周知,将文本与旁边的图标对齐是一项艰巨的任务。
Atom:
前 Twitter 平台:
iOS:
Mozilla:
YouTube:
有时候图标高过文本:
有时候文本高过图标:
有时候两者都未能完美居中:
有些图标就是普通的 HTML 表单控件:
有些添加了艺术效果:
感谢 @bee 提供图片
有时人们会创造性地实现完美对齐:
但总体上,这是个让人绝望的游戏:
问题在于,CSS 也不能提供什么帮助。vertical-align
有 13 种取值,但没有哪一个能有效地将文本和图标对齐:
text-align: middle
最接近对齐,但是按 x-height 而不是 cap-height 对齐,看起来还是不平衡:
这就是人们如此热爱 Web 编程的原因:总是充满挑战。
图标字体
对齐矩形相对简单。对齐文本则很困难。图标是矩形。如果我们把图标放到字体文件中会怎样呢?
现在,我们什么也对不齐了:
我们也没法设置图标大小。在上面的例子中,所有图标的字体大小和行高都做了同样的设置。如你所见,它们的大小、边距都不一样,没有哪一个真正地对齐了。
尽管有很多缺点,并且几乎没有任何好处,各家公司还是争先恐后地到处添加图标字体。结果就像下面这样:
macOS 10.14 → macOS 10.15
操作符不再是垂直对齐的,而且还很模糊。这都是因为切换到图标字体所致。
苹果公司是如此执着于图标字体,以至于他们甚至毁了 QuickTime 录制按钮:
看看吧:
是的,直到今天还是这个样子。计算器也一样。
但远不止这些,请看下面这些例子。
一:
二:
三:
四:
五:
六:
七:
和文本对齐一样,糟糕的图标对齐也是数不胜数。
技能问题
不只是程序员会遇到居中失败的问题。设计师也会:
当前版本/ 我的修复
图标的问题在于,有时候还需要考虑它们的形状:
糟糕的居中 / 良好的居中
三角形处理起来特别难:
有时候太靠左:
有时候太靠右:
甚至可能过高(又是行高惹的祸):
水平居中
你可能会想,只有垂直居中才这么难。不是这样的,水平居中也很难:
我认为这并没有什么深层次的原因,一切皆因人们不够严谨:
拜托!
这是个深思熟虑的决定吗?
我不得而知。图标也有这样的问题:
文本也是:
我们能做些什么:设计师
那么问题是什么?
一切皆因字体而起。现在,文本块的边界框看起来像下面这样:
问题在于,它还可以像下面这样:
或这样:
现在,如果你试图通过居中边界框来居中文本会怎样?
虽然矩形实现了完美居中,但文本还是偏了。
但是,即使字体参数可以不平衡,也不意味着它确实如此。现实中会发生什么呢?
事实上,大部分流行的字体都有点轻微的不平衡,许多还很明显:
字帽高度百分比
10% 不是个小数,在 13 号字体中可以占到一个完整的像素。如果再放大 2 倍,就比较明显了。
大体上,Segoe UI 就是 Github 在 Windows 上看上去像下面这样的原因:
解决方法很简单:收紧边界框,居中就是小事一桩了:
如果你使用 Figma,也可以这样做了(虽然不是默认的):
我们能做些什么:字体设计师
如果你是一名字体设计师,请像下面这样设置字体参数,使ascender − cap-height = descender
:
在视觉上像下面这个样子:
重要提醒:你不必将 ascenders/descenders 扩展到边界。如上图所示,ascender 空间并没有得到充分利用。只要让上述数值可以匹配即可。
无论是 Web 开发还是原生开发,为了避免麻烦,务必选择遵循此规则的字体。SF Pro Text、Inter 和 Martian Mono 似乎都已经做到了这一点,所以使用它们不需要额外做什么工作就可以实现完美居中。
要了解更多信息,可以阅读“字体大小没用;让我们来修复它”这篇文章。
我们能做些什么:Web 开发人员
从开发人员的角度来看,这有点棘手。
首先要搞清楚的是,你需要知道你将使用哪种字体。遗憾的是,如果你计划替换字体,这不会起作用。
我们将使用 IBM Plex Sans。它的参数如下:
你在设置font-size
时,你设置的是 UPM(这个也等于1em
)。然而,文本块实际占用的空间是 ascender 和 descender 之间的空间。
经过简单的计算,我们发现,设置padding-bottom: 0.052em
可以得到想要的结果:
如下所示:
查看字体参数,请点击这里(ascender、descender、sCapHeight)。
现在,我们已经把问题解决了,对齐图标也不那么难了。设置vertical-align: baseline
,然后下移(iconHeight - capHeight) / 2
:
遗憾的是,你既要知道字体参数,又需要知道图标大小。但至少,这个方法有效。
我们能做些什么:图标字体
不要再使用字体图标。
使用普通的图片格式。为了帮你做出决策,我画了下面这张图:
看看苹果公司怎么费力地将复选标记放入矩形内,以及将矩形放到文本标签旁:
然而他们还是失败了!
没有什么比对齐两个矩形更容易的了。没有什么比尝试对齐被任意数量空白包围的文本更困难的了。
这是一场我们赢不了的游戏。
我们能做些什么:视觉补偿
作为开发人员,我们只能通过数学的方法实现矩形的完美对齐。因此,对于任何需要手动补偿的内容,可以将其放置在一个足够大的矩形中,并在其中实现图标视觉效果的平衡:
我们能做些什么:所有人
请一定注意。请务必小心。糟糕的居中可能毁掉原本不错的 UI:
但恰当的文本对齐可以让你的 UI 美妙如歌:
即使这很难。即使没有便捷的工具。即使你不得不搜寻解决方案。我相信,只要我们齐心协力,就能找到把一个矩形套在另一个矩形里而又不会把它弄乱的方法。
就我个人而言,我希望生活在一个 UI 美丽而平衡的世界里。我相信你也是。最终,一切都是值得的。