一次内联元素错位引起对line-height的思考

做者:李一睿css

line-height 对于一个前端小可爱来讲,应该是一个会常常碰面的老朋友了。但是有一天,我忽然发现本身好像对他没那么了解,他也没有外表看起来的那么简单。html

事情的通过是这样的……前端

在偶然一次工做中,我写了这样的模板:字体

<div>
    <span class="name">重大疾病险</span>
    <span class="tip">保额每个月可累计</span>
</div>
复制代码
div{
    font-family: "PingFang SC";
}
.name{
    line-height: 20px;
    font-size: 20px;
}
.tip{
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
}
复制代码

两个相邻的内联元素,字体一大一小,行高相同,因为第二段文字须要有字多状况就自动去下一行的效果,因此第二个spaninline-block我畅想的结果是,两个 span 高度都是 20px, div 高度也是 20px,多么完美。但结果每每不近人意……spa

div 的高度怎么是 28??3d

再一看子元素,一个 28 一个 20??code

  • 疑问1:难道是 line-height 对行内元素不生效??orm

    然而规范告诉我,对于非替代的 inline 元素,它用于计算行盒(line box)的高度。cdn

  • 疑问2:既然生效了,为何审查元素看着是 28,不是 20 呢?htm

    对于文原本说,存在一个内容区域(content area)。你能够理解为,用光标选中这行文字时带背景的区域。他同时受 font-family 和 font-size 的影响。就算是相同的字号,若是字体不一样,‘你所看到’的高度也是不同的,同窗们能够本身尝试一下。这里强调你所看到的,也就是咱们这里的 28px,它实际上是这个文本内容区的高度,而内容区的高度并非真正的高度,也就是说,它不会影响这个元素真正的尺寸,也不会撑起父元素的高度,因此只是一个你看起来的高度。而对于行内元素来讲,真正影响它高度的就是line-height

    在这里,咱们能够经过改变他们的 font-family 来证明一下。

    div{
          font-family: "HelveticaNeue";
      }
      .name{
          line-height: 20px;
          font-size: 20px;
      }
      .tip{
          display: inline-block;
          line-height: 20px;
          font-size: 14px;
      }
    复制代码

    能够看到,更改了字体以后,.name的高度由28变成了24,.tip因为是inline-block因此高度没变,可是父div的高度依然是28px,说明content area并不会影响父元素的真实高度。

  • 疑问3:那如何看到它真正的高度?

    你可能也发现了,第二个 span 是inline-block,它的高度就是 20px,那咱们将第一个span也设置成inline-block来看一下。

    果真,它的高度终于变成了咱们指望的 20px。
    那咱们再来看一下父元素div的高度:

    !!怎么仍是 28px??

  • 疑问4:两个子元素都已是 20px 了,为何父元素仍是 28px?

    这里先声明两个问题:

    1. 证实前面疑问2中说的没错,content area 是不会影响实际尺寸的,如今咱们元素都是 20px 了,可父元素依然仍是 28px。
    2. 咱们将第一个 span 设置成inline-block以后,能够看到它的尺寸已经变成了 20px,但这并不表明这它就没有 content area 了,或者它的 content area 变成了 20px。你能够理解为咱们给他外面包了一层盒子,你能够看到盒子的真正的尺寸,而 content area 在它里面,你只是看不到罢了。更况且,它是一个影响不了谁的东西。

    接着回到咱们的问题,仔细看上图,能够发现,两个高度都是 20px 的子元素,上下都有必定的间隙;再仔细看,发现它俩没对齐,红色背景的靠上,粉色背景的靠下,它俩之间稍微有些错位。就是这些,让咱们的父元素被撑成了 28px。那它们又是从哪里来的呢?

    既然是对不齐致使父元素被撑高了,那 CSS 中相关对齐的属性,咱们很容易想到是vertical-align,难道是它搞得鬼?那咱们试着改一下它们的vertical-align

    vertical-align:top,上面对不齐了

    vertical-align:middle,好像跟以前差异不大……

    虽然说这些属性值都没能让他们对齐,但能够发现确实是与它有关的,多是咱们哪里使用不当,影响了这个属性?那咱们就去了解一下vertical-align是怎么对齐的,起初咱们不设置的时候,会取它的默认值:baseline—— 基线对齐。

    内联元素默认是基线对齐的,而基线就是指行框盒子中字母'x' 的下边缘:

    诶??再仔细看看咱们以前对不齐的那张图,你会发现,虽然元素没对齐,可是文字下端是对齐的,这不就是正常的基线对齐吗!这下就说的通了。

    划重点!!

    行内元素的对齐方式默认是基线对齐,也就是都与 x 的下边缘对齐。这两个 span 的高度是同样的,都是 20px,然而重点就在于它们的字体大小不同。而文本在若是设置了line-height,是会基于line-height居中的,也就是说,它们分别在各自高度相同框框中居中,但因为字号大小不同,因此文字底部是对不齐的,但他们又须要基线对齐,因此它俩开就必需要错位一下。

    这里引用一下鑫旭大神的图:

  • 疑问5:那这是否是就说明,咱们把两个元素的行高设置成不同,就能够不错位把父元素撑高了?

    这里咱们分别给两个span设置与本身字体大小同样的行高:20px 和 14px,能够看到它俩已经没有向外错位了,可是父元素的高度并无如期,仍是 28px。怎么回事?难道还有别的东西再影响它?

    你猜对了,但这是个咱们看不见的东西。引用一下张鑫旭大神的叫法——幽灵空白节点。

    “幽灵空白节点”是内联盒模型中很是重要的一个概念,具体指的是:在 HTML5 文档声明 中,内联元素的全部解析和渲染表现就如同每一个行框盒子的前面有一个“空白节点”同样。这 个“空白节点”永远透明,不占据任何宽度,看不见也没法经过脚本获取,就好像幽灵同样, 但又确确实实地存在,表现如同文本节点同样,所以,我称之为“幽灵空白节点”。

    既然看不见,那咱们能够拿一个看的见的 x 字符来伪装它。

    <div>
          <em>x</em>
          <span class="name">重大疾病险</span>
          <span class="tip">保额每个月可累计</span>
      </div>
    复制代码
    div{
          font-family: "PingFang SC";
      }
      em{
          display:inline-block; /*为了审查元素看到的不是content area*/
          font-style:normal;
      }
      .name{
          line-height: 20px;
          font-size: 20px;
      }
      .tip{
          display: inline-block;
          line-height: 20px;
          font-size: 14px;
      }
    复制代码

    这个 'x' 字号和行高都没有设置,字号是继承下来的 20px,元素行高默认是 1.x(1.x 倍的 font-size),具体数值还有待研究,但绝对是 >1 的,由图可见,什么都没有设置的状况下,这个 'x' 的高度就是 28px,也就表明着,那个幽灵空白节点的高度就是 28px。

    那咱们将幽灵空白节点的行高设小一些不就行了?但是这个幽灵节点,看不见摸不着,怎么设啊。别忘了,line-heigt是可继承性的,咱们给父div设置line-heigt,幽灵节点天然就会继承。

如何解决

明白了上述的疑问以及原理,接下来就看下怎么解决这个问题。

解决一

咱们能够给父divline-height设置一个很小的值

div{
    line-height: 5px;
    font-family: "PingFang SC";
}
em{
    display:inline-block; /*为了审查元素看到的不是content area*/
    font-style:normal;
}
.name{
    line-height: 20px;
    font-size: 20px;
}
.tip{
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
}
复制代码

这样,幽灵节点的行高就只有 5px,父元素行高 20px,没毛病。但这个方法还不够完美,由于你须要想一下这个很小的值……

解决二

当 line-height 设置为一个无单位的数值时,表示是某倍的font-size。

div{
    line-height: 1;
    font-family: "PingFang SC";
}
em{
    display:inline-block; /*为了审查元素看到的不是content area*/
    font-style:normal;
}
.name{
    line-height: 20px;
    font-size: 20px;
}
.tip{
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
}
复制代码

给父元素设置line-height为1,这样,子元素高度都是本身的font-size,包括幽灵空白节点。这样就不会再有人无心间撑高父元素了。固然,除非你的幽灵空白节点继承下来了一个很大的 font-size, 这点你得明白。

解决三

既然行高能够与 font-size 有关,font-size 也是可继承的,那咱们将父元素的 font-size 设为 0

div{
    font-size: 0px;
    font-family: "PingFang SC";
}
em{
    display:inline-block; /*为了审查元素看到的不是content area*/
    font-style:normal;
}
.name{
    line-height: 20px;
    font-size: 20px;
}
.tip{
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
}
复制代码

能够看到,咱们模仿的那个幽灵节点已经没有了,宽高都是 0 了,父元素的高度也天然就回到了 20px。

总结

以上,能够说是我对行内元素对齐问题的一些思考总结吧。若是你还有疑问,能够再多看几遍,本身尝试一下再继续思考思考。这个问题我也是来来回回想了好多遍,也欢迎你们评论提问,咱们能够一块儿讨论~

前端小白,有讲解错误或不全之处,还望大佬们嘴下留情,欢迎指正~

相关文章
相关标签/搜索