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

栏目: Html · 发布时间: 6年前

内容简介:作者:李一睿line-height 对于一个前端小可爱来说,应该是一个会经常碰面的老朋友了。可是有一天,我突然发现自己好像对他没那么了解,他也没有外表看起来的那么简单。事情的经过是这样的……

作者:李一睿

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

事情的经过是这样的……

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

<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,多么完美。但结果往往不近人意……

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

div 的高度怎么是 28??

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

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

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

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

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

    对于文本来说,存在一个内容区域(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;
      }
    复制代码
    一次内联元素错位引发对line-height的思考 一次内联元素错位引发对line-height的思考 一次内联元素错位引发对line-height的思考

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

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

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

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

    果然,它的高度终于变成了我们期望的 20px。

    那我们再来看一下父元素 div 的高度:

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

    !!怎么还是 28px??

  • 疑问4:两个子元素都已经是 20px 了,为什么父元素还是 28px?

    这里先声明两个问题:

    inline-block
    

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

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

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

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

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

    vertical-align:middle ,好像跟之前差别不大……

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

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

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

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

    划重点!!

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

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

    一次内联元素错位引发对line-height的思考
  • 疑问5:那这是不是就说明,我们把两个元素的行高设置成不一样,就可以不错位把父元素撑高了?

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

    这里我们分别给两个 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;
      }
    复制代码
    一次内联元素错位引发对line-height的思考

    这个 '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;
}
复制代码
一次内联元素错位引发对line-height的思考 一次内联元素错位引发对line-height的思考

这样,幽灵节点的行高就只有 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, 这点你得明白。

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

解决三

既然行高可以与 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;
}
复制代码
一次内联元素错位引发对line-height的思考 一次内联元素错位引发对line-height的思考

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


以上所述就是小编给大家介绍的《一次内联元素错位引发对line-height的思考》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First EJB(中文版)

Head First EJB(中文版)

KathySierra,Ber / 中国电力出版社 / 2006-9 / 79.00元

有些人只是想通过认证来取悦挑剔的老板,但相信你不是这种人。确实,你也想通过Su n认证业务组件开发人员(SCBCD)考试,但不仅如此,你还需要真正把EJB用到实处。你要构建应用,要对付最后期限,如果通过考试之后第二天早上就把你学过的EJB知识忘得一干二净,你肯定会受不了。 我们会看着你稳稳当当地通过考试,而且会帮你在实际中使用EJB。你会深入地了解EJB体系结构、会话、实体和消息驱动......一起来看看 《Head First EJB(中文版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具