资讯专栏INFORMATION COLUMN

理解 line-height 和 vertical-align

junfeng777 / 1767人阅读

摘要:我认为应该将理解为。如果的值是,高度就是等于。中所有的最高点以及最低点决定了它的高度该计算包括了的高度,后文会提到。非替换元素的的,以及并不会影响高度的计算。并不是两条之间的距离。元素的垂直中点位置与父元素的基线加上一半的位置对齐。

文章 GitHub 地址:https://github.com/afishhhhh/blog/issues/4
文章如有错误,请各位能够指出。

几个概念

line box:包裹 inline box 的一个盒子,一个或多个 line box 堆叠撑起一个 HTML 元素。

inline(-level) box:可以是一个由行内元素包裹的盒子,也可以是一个纯文字的匿名盒子。

content area:对于非替换元素来说,content area 的范围由 font-size 以及字体本身决定;对于替换元素来说,由元素自有宽高决定。

baseline:一个元素基线的位置由该元素内字母 x 底部所在的位置决定,当然字体不同基线所在的位置也就不同。

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

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

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

关于 content areaW3C 有一段这样的解释:

CSS 2.1 does not define what 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 的定义就是自有宽高加上 margin,padding 以及 border。我认为应该将 content area 理解为 content box

line box 高度

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

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

inline-block 元素:

div {
  background-color: #ccc;
  color: #fff;
}
span {
  display: inline-block;
  height: 30px;
  margin: 10px;
  background: #fff;
  color: red;
}
xxxxxxxxx

这里 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-family: Sana;
}
span {
  background: #fff;
  color: red;
}
xxxxxxxxx

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

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

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

非替换元素的的 marginpadding 以及 border 并不会影响 line box 高度的计算。当一个 inline-level boxline-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;
}
xxx

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; }

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

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


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

总结一下存在间隙原因:

strut 存在 line-height

vertical-align 默认值为 baseline

对应的解决方案:

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

vertical-align 设置为其他值

line-height

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

On a block container element whose content is composed of inline-level elements, "line-height" specifies the minimal height of line boxes within 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 properties. We call that imaginary box a "strut."

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

normalline-height 的默认值,W3C 对它并没有一个明确的定义。normal 会将 content area 作为一个计算因素。

line-height 并不是两条 baseline 之间的距离。

line-height 的值推荐使用数值,而不是使用 em 单位,因为 em 单位会根据从父元素继承到的 font-size 来计算行高。

vertical-align

W3Cbaseline 以及 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.com/eric/css/inline-format.html

https://www.zhangxinxu.com/wordpress/2015/08/css-deep-understand-vertical-align-and-line-height/

https://www.w3.org/TR/CSS2/visudet.html#inline-box-height

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/53470.html

相关文章

  • 深入理解css之vertical-align

    摘要:但实质上,只要是内联元素,这两个元素都会同时在起作用。而解决方案可以有以下几种元素不使用基线对齐,可以改为对齐元素块状化设置为设置为总结讲解了的各类属性值及其效果起作用的前提是内联元素与都是同时作用在内联元素上的 前言 vertical-align用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直对齐方式。也就是说,对于块级元素,vertical-align...

    cgh1999520 评论0 收藏0
  • CSS魔法堂:深入理解line-heightvertical-align

    摘要:下的属性值详解以下内容均在中测试默认对齐方式这里作为参考系,而它的就是所要对齐的了。没有任何变化。那改变又如何呢为了让的清晰可见,特意添加一个的包裹着。 前言 一直听说line-height是指两行文本的基线间的距离,然后又说行高等于行距,最近还听说有个叫行间距的家伙,@张鑫旭还说line-height和vertical-align基情四射,贵圈真乱啊。。。。。。于是通过本篇来一探究竟...

    avwu 评论0 收藏0
  • 【学习笔记】CSS深入理解vertical-align

    摘要:上例中,左边盒子的基线为其底边缘,右边盒子的基线为的基线将右边盒子的行高设置为,即这个的高度为,位置处于中间。 vertical-align的值 线类:baseline(默认), top, bottom, middle 文字类:text-top, text-bottom 上标下标类:sub, super 数值:1px, 1em - 在baseline对齐的基础上上下偏移一定数值 百分...

    ermaoL 评论0 收藏0
  • 关于 vertical-align 的一些理解

    摘要:关于的条参考线以及。关于和之间的关系。目标元素的的垂直平分线,与父元素内匿名的对齐。垂直平分线,这个容易理解。要比这些字母的顶端再高一些。 前言 关于 vertical-align,我们很容易想到,这不就是告诉我们元素在纵向上和什么对齐的属性吗?而事实上,正是这种宽泛的说法导致了我们对其的理解存在许多不确定性。事实上,对齐这两个字其实牵涉到4个对象:即哪个对象的哪条线,与哪个对象的哪条...

    lowett 评论0 收藏0
  • 深入理解 CSS:字体度量、line-height vertical-align

    摘要:接下来说句听起来很奇怪的话一个内联元素有两个高度高度和实际区域高度是我自己发明的单词,它表示对人类有效的高度,你在其他地方是看不到这个单词的。你没看错,是计算的一些细节对于内联元素,和会增大区域,但是不会增大不是的高度。 本文为饥人谷讲师方方原创文章,首发于 前端学习指南。 这是一篇译文,对 inline 和 inline-block 的元素剖析非常给力。 原文:Deep dive C...

    Dean 评论0 收藏0
  • 理解 line-height vertical-align

    摘要:我认为应该将理解为。如果的值是,高度就是等于。中所有的最高点以及最低点决定了它的高度该计算包括了的高度,后文会提到。非替换元素的的,以及并不会影响高度的计算。并不是两条之间的距离。元素的垂直中点位置与父元素的基线加上一半的位置对齐。 文章 GitHub 地址:https://github.com/afishhhhh/blog/issues/4文章如有错误,请各位能够指出。 几个概念 ...

    jzzlee 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<