3

案发

1.这些文字是如何摆放这么整齐的?为什么这个庞然大物的底部能对齐,顶部没对齐?为什么第二行与第一行的间距那么大?

clipboard.png

2.为什么光秃秃的p标签没有高度,为什么在p标签中写入文字就有高度了呢?真的是因为文字大小撑起来的吗?

clipboard.png

clipboard.png


取证

  1. vertical-align是主谋之一,使得庞然大物的底部对齐

  2. line-height是另一主谋,导致顶部没对齐以及巨大间距和p高度

  3. 匿名文本em框font-size,内容区行间距,行内框行框行内非替换元素间接或直接参与了犯罪

分析

场景回顾

<body style="padding:0 400px;border:1px solid #000">
    <p style="font-size:16px;line-height:16px;">
        This is the content of the element p. Here is inline element. I am glad that you  come to read here.I hope that 
        <strong style="font-size:40px;">you</strong> can learn more from here. So  just code, it's a great things. Let's go!!!.
    </p>
</body>

身份鉴定

  1. 匿名文本:英文名anonymous text。简单来说就是所有未包含在行内元素中的字符串。比如说案发现场的This is the......I hope that

  2. em框:别名字符框(character box)。em框在字体中定义。em框在css中不可见,是一个比较抽象的概念。这里只需要知道font-size确定了各个em框高度即可

  3. font-size:字体大小,与em框有关

  4. 内容区:在行内非替换元素中,内容区是元素中各个字符的em框串在一起构成的框。在行内替换元素中,内容区是元素的固有高度再加上可能有的外边距、边框和内边框。

  5. 行间距line-heightfont-size之差,这个差分为两半,分别应用到内容区的顶部和底部。行间距只适用于行内非替换元素

  6. 行内框:这个框通过向内容区增加行间距来描述。对于非替换元素,元素行内框的高度刚好等于line-height的值。对于替换元素,元素行内框的高度恰好等于内容区的高度,因为行间距。

  7. 行框:这是包含该行中出现的行内框的最高点最低点的最小框。换句话说,行框的上边界要位于最高行内框的上边界,而行框的底边要放在最低行内框的下边界。

  8. 非替换元素:如果元素的内容包含在文档中,则称之为非替换元素。比如说

    <p>Inner content</p>或<div>Inner content</div>
  9. 替换元素:用作为其他内容占位符的一个元素。比如说

    <img src="test.gif" />或者<input type="radio" />

重要提示:为了便于接下来的分析过程,请先了解他们的身份,然后带着疑问去参与分析。

模拟作案

  1. 首先是字体创建,该过程伴随着em框的生成,这个框是不可见的。开发人员无法控制该框大小。

  2. 每一个字符的产生都代表em框的生成。(那么这些字符是如何摆放的?为什么是浏览器呈现给我们的样式?人们写字的时候总是不经意间会写歪,那么浏览器又是如何做到对齐)

  3. 所有字符都全部action后,em框连在一起形成了内容区。这个区域依然不可见,很抽象。开发者无法直接控制,只能通过font-size间接影响em框从而影响内容区的大小。大多数情况下可以认为font-size大小即为内容区大小。

  4. 内容区生成后,行内框也即将生成。这个时候,行间距吵闹着要把自己分成两半,一半放在内容区的头上,另一半下放在内容的底部,这样才显得恩爱嘛。

  5. 当爱情发生后总会产生些什么。于是行内框就诞生了,内容区和行间距的完美组合就是行内框。行内框是可见的。

  6. 所有的行内框都出生后,就得按照一定的规则制造一个包容它们的容器了,这就是行框。既然要包含它们,那必然得照顾最高和最矮的那个了。

以上是一般案例的发生,图解如下

clipboard.png

代码如下:

<body style="padding:0 400px;border:1px solid #000">
    <p style="font-size:16px;line-height:16px;background:#af3;border:1px solid red">
        This is the content of the element p. Here is inline element. I am glad that you  come to read here.I hope that 
        <strong style="background:yellow;">you can learn more from here</strong> . So  just <span style="background:blue">code, it's a great things. Let's go!!!.</span>
    </p>
</body>

黄色蓝色区域代表内容区(在这同时也表示行内框),如果line-height与font-size大小不一时,使用background添加颜色时,作用的是内容区(content)。

温馨提示:思考时可以先考虑这一行中有哪些元素,再参照上述过程进行模拟。

案件实战

有了以上的基础后,这里便开始对两个案件合并进行透彻的剖析(因为问题牵扯的本质是一样的)。

代码重温:

    <body style="padding:0 400px;border:1px solid #000">
        <p style="font-size:16px;line-height:16px;">
            This is the content of the element p. Here is inline element. I am glad that you  come to read here.I hope that 
            <strong style="font-size:40px;">you</strong> can learn more from here. So  just code, it's a great things. Let's go!!!.
        </p>
    </body>

效果重温:

clipboard.png

问题重温:匿名文本和strong标签的内容是如何对齐的?line-height都是16px,第二行的间距还是那么大?

问题解决:首先是对齐的问题,关于行内元素的对齐就不得不提到vertical-align属性

浏览器代理(userAgentStylesheet)给所有行内元素vertical-align的属性默认设置成了baseline。baseline这个属性值要求元素的基线与父元素的基线对齐。

clipboard.png

clipboard.png
这张图特意放大了

图中红色区域就是基线。css规范中对基线是否有明确规定?这一点我不太清楚。这里讲下个人的理解吧,基线是字符的特有属性,在字体被设计时就被确定好的。开发者无法控制。

由于userAgentStylesheet默认vertical-align属性值为baseline,所以它们就工整的对齐了。

第二个问题,第二行间距为什么如此大?

line-height明明都是16px。

原因很简单,line-height在应用到块级元素时,它定义的是元素中文本基线之间最小距离。也就是说这不是一个固定死的数值,只是一个最低要求。

首先p标签是块级元素,其次line-height设置的大小与匿名文本的font-size一样,这导致内容区与行内框大小一致。然而对于strong标签里的文本来说,由于行内框小于内容区的大小,且行内框在内容区垂直居中

clipboard.png
颜色强调

首先,每行的行框顶端是紧靠着上一行行框的底端。正如图中所见,着色区域都是内容区。因为前三行的font-size和line-height大小一致,所以行框即是着色区。但是第四行的内容区并不等于行框大小。

单独审视第四行,这里有两个匿名行内框(hope that 和can learn more)和一个行内元素strong。一共三个行内框,其中匿名行内框的大小等于font-size,而strong标签的行内框却远小于内容区的大小(font-size),由于行间距是对半上下分布的(参考案件模拟里的第四条),所以此时行内框的位置是在内容区是垂直居中的。

clipboard.png
strong元素行内框

按照行框的生成过程(案件模拟)来看,这里行框的顶端是由strong元素的行内框顶端确定,底端则是有匿名文本的行内框的底端确定。

clipboard.png

图中箭头所指即为行高。

至此,已经解决了对齐和为什么第二行间距如此大的问题。

当p标签中没有任何内容时,p的高度为0.当p中随意写入文本时,p会生成一个高度。这并不是被文本撑起来的,而是行框、行内框的作用。注意,通常情况下line-height有个默认值1.2。
这里就不细讲了,可以当做思考题,希望对各位有帮助。


我的第一次给了segmentFault。。。呜呜


Blcover
384 声望11 粉丝

码码码码