好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

深入理解 line-height 和 vertical-align

几个概念

line box:包裹 inline box 的一个 盒子 ,一个或多个 line box 堆叠 撑起一个 HT ML 元素。 inline(-level) box:可以是一个由 行内元素 包裹的盒子,也可以是一个纯文字的匿名盒子。 content area:对于非替换元素来说,content area 的范围由 font -s ize 以及字体本身决定;对于替换元素来说,由元素自有 宽 高决定。 baseline:一个元素基线的位置由该元素内字母 x 底部所在的位置决定,当然字体不同基线所在的位置也就不同。

通过一段代码可以理解一下:

div {
  background-color:  # ccc;
  font- Size:  20px;
  color: #fff;
}
span {
  color:  red ;
}
<div>文字1<span>文字2</span>文字3</div>

白色 的文字就是一个匿名 inline box, 红色 的文字是一个由 span 包裹的 inline box。这三个 inline box 组成一个 line box,可以理解为灰色的区域,因为在这个例子里就是由一个 line box 撑开了 div 。如果有多行的文字,那就有多个 line box。

关于 content area,W3C 有一段这样的解释:

CSS 2.1 does not define w hat the content area of an inline box is (see 10.6.1 above) and thus different UAs may draw the backgrounds and borders in different places.

这篇文章 对非替换元素 content area 的定义就是自有宽高加上 m arg in,padding 以及 border。我认为 应该 将 content area 理解为 content box。

line box 高度

浏览器会计算 line box 中每一个 inline box 的高度,对于不同的 inline box 计算方式有所不同:

如果是一个替换元素(比如 img , input ),inline-* 元素 或者 是 flexbox 中的子元素,高度由其 mar gin box 决定;

inline-block 元素:

div {
  background-color: #ccc;
  color: #fff;
}
span {
  dis play : inline-block;
  h ei ght: 30px;
  margin: 10px;
  background: #fff;
  color: red;
}
<div>xxx<span>xxx</span>xxx</div>

这里 span inline box 的高度就是 height + margin 2 。如果 height 的值是 auto,高度就是等于 line-height + margin 2。

如果是一个非替换元素,高度由它的 line-height 决定,而不是 content area,虽然有时候看起来像 content area 撑开了 line box 的高度。

div {
  background-color: #ccc;
  font-size: 20px;
  color: #fff;
  font-f ami ly: Sana;
}
span {
  background: #fff;
  color: red;
}
<div>xxx<span>xxx</span>xxx</div>

这张图片可以明显地看出撑开 line box 的是 line-height,而不是 content area。

这篇文章 用了 virtual-area height 来表示 line-height 撑开的高度,而我的理解其实就是 inline box 的高度。

line box 中所有 inline box 的最高点以及最低点决定了它的高度(该计算包括了 strut 的高度,后文会提到 strut)。

非替换元素的的 margin,padding 以及 border 并不会影响 line box 高度的计算。当一个 inline-level box 的 line-height 小于 content area 的时候,line box 的高度就会小于 content area,此时元素的 background 以及 padding 等就会溢出到 line box 之外。

以下代码可以说明这个问题:

div {
    background: #eee;
    border: 1px solid #000;
    box-sizing: border-box;
    font-size: 50px;
    line-height: 10px;
}
span {
    background: red;
    margin: 10px;
    padding: 10px;
}
<div><span>xxx</span></div>

leading:

content area 的高度与 inline box 的高度差就是 leading,这个 leading 会等分被添加到 content area 的顶部与底部,所以说 content area 永远 位于 inline box 的中间(垂直居中)。

strut:

浏览器认为每一个 line box 的起始位置都存在一个宽度为 0,没有任何字符的 匿名 inline box,称为 strut,这个 strut 是会从父元素继承 line-height 的,因此它的高度会影响整个 line box 高度的计算。

一个例子

div { background: #eee; border: 1px solid #000; box-sizing: border-box; }
<div><img src="./image.png" alt=""></div>

在图片中可以看到 img 与外层的 div 存在一个间隙,这就是上文提到的 strut 造成的。

在这个例子中,默认情况下 img 的底边与父元素的基线对齐( img { vert ical -align: baseline } ),而这个基线实际上就是 strut 基线所在的位置。如下图所示:

strut 其实就相当于一个不可见的字母 x,上文已经提到 strut 本身是具有 line-height 的,所以就导致图片底部多了一段间隙。

总结一下存在间隙 原因 :

strut 存在 line-height vertical-align 默认值为 baseline

对应的解决 方案 :

修改 strut 的 line-height,因为 strut 的 line-height 不是能够直接设置的,所以需要设置父元素的 line-height,然后让 strut 继承,或者修改 font-size 将 vertical-align 设置为其他值line-height

W3C 中对于 line-height 的解释是这样的:

On a block cont ai ner element whose content is composed of inline-level elements, 'line-height' s PE cifies the minimal height of line boxes w IT hin the element. The minimum height consists of a minimum height above the baseline and a minimum depth below it, exactly as if each line box starts with a zero-width inline box with the element's font and line height PR operties. We call that imaginary box a "strut."

我的 简单 理解是,对于由行内元素组成的块级元素而言,line-height 决定了 line box 的最小高度,浏览器会假定每一个 line box 以一个宽度为 0 的 inline box (strut) 开始 ,而这个 strut 从父元素继承到 font 以及 line-height。

normal 是 line-height 的默认值,W3C 对它并没有一个 明确 的定义。normal 会将 content area 作为一个计算 因素 。 line-height 并不是两条 baseline 之间的 距离 。 line-height 的值推荐使用数值,而不是使用 em 单位,因为 em 单位会根据从父元素继承到的 font-size 来计算行高。

vertical-align

W3C 对 baseline 以及 middle 的定义如下:

baseline: Align the baseline of the box with the baseline of the parent box. If the box does not have a baseline, align the bottom margin Edge with the parent's baseline.

元素基线与父元素基线对齐,如果元素没有基线,比如 img ,则使用 margin 底边与父元素基线对齐。

middle: Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent.

元素的垂直中点位置与父元素的基线加上一 半 x-height 的位置对齐。

参考

Deep dive CSS: font metrics, line-height and vertical-align
https://meyerweb测试数据/eric/css/inline-format.html
https://HdhCmsTestzhangxinxu测试数据/wordpress/2015/08/css-deep-understand-vertical-align-and-line-height/
https://HdhCmsTestw3.org/TR/CSS2/visudet.html#inline-box-height

总结

以上是 为你收集整理的 深入理解 line-height 和 vertical-align 全部内容,希望文章能够帮你解决 深入理解 line-height 和 vertical-align 所遇到的问题。

如果觉得 网站内容还不错, 推荐好友。

查看更多关于深入理解 line-height 和 vertical-align的详细内容...

  阅读:14次