文字间距翻车,规范跟实际渲染为啥打架,咋整?

2,048字
9–13 分钟
in

写网页的时候给文字加个letter-spacing想让字松快点,结果发现居中的按钮文字偏左了,或者从右往左读的阿拉伯文排版直接裂开。这破事还真不是手抖,而是CSS规范跟浏览器实现打了几十年的架。letter-spacing本意是控制字符之间的额外空白,好比排队时每个人之间加半米距离。但规范说“之间”就是两个人中间的空隙,浏览器却理解成在每个字符的屁股后面加空白,导致队尾多出一段空地。更离谱的是,火狐跟Chrome对“字符末尾”的定义还不一样,一个跟着阅读方向走,一个死认右侧。这就导致同样的代码在不同浏览器里歪七扭八,尤其居中布局时文字死活站不到C位。

目录

浏览器咋渲染的

打开任意网页,给一段文字加上letter-spacing: 0.2em,比如一个居中的按钮文字“点我下单”。规范理想的效果是每个字之间均匀加间距,首尾没有多余空白,文字整体还是稳稳钉在正中间。但实际跑起来,浏览器会在最后一个字的右侧也塞上0.2em空白,整段文字就被向右推了一截。如果把按钮背景高亮显示,能明显看到文字不在背景的正中央,左边空白比右边少一截。

这种“末尾补一刀”的渲染方式早成了行业潜规则。看看下面这段代码在Chrome、火狐、Safari里跑出来的效果:

<div style="text-align: center; background: lightblue; padding: 1rem;">
  <span style="letter-spacing: 0.3rem;">点击购买</span>
</div>

光看背景色的左右内边距,肉眼就能发现“点击购买”四个字靠左了,右边多出一截空气。要是换成从右往左的希伯来文,Chrome依然把额外空白加在右侧(也就是行首位置),文字开头先空一截;火狐则加在左侧(行尾),两种表现直接把跨浏览器排版搞成玄学。

临时咋补救

既然浏览器死活不改,只能自己动手填坑。最土但管用的办法是给文字套个父容器,反向补空白。比如按钮文字加了letter-spacing: 0.2rem导致末尾多出0.2rem偏移,就在父容器右边用负的margin-right或者左边用正的padding-left给拽回来。但得注意,这个偏移量在不同浏览器里可能因为字体渲染略有差异,最好多测几个环境。

方案一:父容器负边距拉回

<div style="display: inline-block; margin-right: -0.2rem;">
  <span style="letter-spacing: 0.2rem;">点我下单</span>
</div>

这样末尾多余空白被父元素的负边距吃掉,文字整体回正。但有个坑:负边距可能让父容器宽度变窄,如果旁边有浮动元素会叠一起。稳妥点把父容器设为inline-block,只收缩到文字实际宽度。

方案二:左右对称补偿

对于居中场景,可以给文字包两层。外层负责居中,内层用相对定位往左偏移半个间距值。例如letter-spacing: 0.4rem导致偏移0.4rem,那就往左挪0.2rem:

<div style="text-align: center;">
  <span style="letter-spacing: 0.4rem; position: relative; left: -0.2rem;">
    确认支付
  </span>
</div>

这个办法对左右两边都生效,偏移量按间距的一半来算。但注意如果文字跨行(比如两行按钮文字),相对定位会让整个块移动,不适用于多行文本。多行场景只能乖乖改父容器的padding,例如原本左右内边距各1rem,改成左边1.2rem、右边0.8rem,手动抹平差值。

未来可能咋整

CSS工作组已经在商量动真格了。两个方向:一是把间距平分到字符两侧,像文字前后各贴半层膜,这样居中对齐自然就正了。二是新增一个属性让开发者自己选间距贴哪,比如letter-spacing-justify: around就平分,letter-spacing-justify: after维持现在的末尾追加。目前工作组倾向于保留旧行为当默认(免得炸掉老网站),同时开放新选项给新项目。

举个例子,以后可能这么写:

/* 平分间距,居中对齐不再歪 */
button {
  letter-spacing: 0.2rem;
  letter-spacing-justify: around;
}

/* 从右往左语言指定间距加在左侧 */
.rtl-text {
  letter-spacing: 0.1rem;
  letter-spacing-justify: before; /* 跟随阅读方向的开头 */
}

不过这套语法还没定稿,等落地少说一两年。眼下遇到文字间距导致的布局歪斜,老老实实用上面两个土办法兜底。写代码时多留个心眼:但凡用了letter-spacing,尤其搭配text-align: centertext-align: right,务必开开发者工具量一下左右空白是否对称。碰上RTL语言,直接放弃治疗改用padding硬调,毕竟跨浏览器一致性的坑掉进去就是半天命。