安卓字体上浮

Posted by CodingWithAlice on March 18, 2020

安卓字体上浮

场景:UI走查的时候,安卓字体上浮2px左右,导致上下居中效果不能实现

参考:Airen的博客(主)、网络博客

总结:非css能解决,原因是在 content-area (字体度量)内部渲染的时候发生的,css 控制的是整个 content-area 居中。能针对特定字体做处理,但是暂时无法通用处理。

单个元素

首先要明确,字体大小和 font-family 是息息相关的,不同的字体,即使设置了 heigth:100px;,盒子高度(content-area)还是不同,如下图:

img

一行内联元素

我们看完单个元素,再来看 一行内联元素 的情况。内联元素组成的一行或者多行内容,行高是通过计算该行内联元素的 最高点-最低点,专业术语称为行盒 line-box

如果单独给一行内的几个元素设置不同的字体,那么就会出现如下图的第二行,由于内联元素的高度,整行高度都是偏大的:

image-20200318183637692

css能起作用么?

在这种情况下,css能做些什么呢?我们熟悉的几个属性:heightmarginpaddingborderline-heightvertical-align

先解释几个简单的:

  • **padding、border **增加了内联元素的 background 区域,但不会增加 content-area 高度
  • margin-top 和 margin-bottom 对内联元素不生效

line-heightcontent-area 的关系可以如下图:

image-20200318225805267

已知,内联元素的 高度计算 是基于 heightmarginborder 属性。

若设置 height:auto;,会出现 line-height = content-area的情况。

注:博主经过对goodle中1千多种字体的尝试,发现 line-height:normal; 时,计算content-area的值是基于字体而来的。

vertical-align 默认为 baseline,基线对齐。但是这个属性值在一行内有两个字体的内联元素时,会导致更大的行盒高度。

image-20200318231259864

vertical-align 设置为 middle 是不是就可以解决呢?规范中描述 middle 取的中间值与 parentbaseline of parent box 有关。并不可靠,这些因素不是css能设置的。

Middle aligns the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent

css还能做什么?

在确定字体的前提下,计算一个内联元素的顶部、底部边缘距离;将距离乘以 font-size 计算出 vertical-align;最后设定所需的 line-height 并计算保持垂直。

line-height: calc(((var(--lineheight) * var(--fontSize)) - var(--valign)) * 1px); }

但是如果字体加载失败,浏览器替换了默认字体,这个计算也就失效了