你真的了解行盒模型吗?

时间:2021-07-20 08:53:32

前言

这一篇博客主要讨论的是行盒模型原理性的东西,如果想学习技巧的话可能这篇博客不适合。组成这个行盒模型的成分有不可替换的行内元素、可替换的行内元素、匿名行框、等。所以为了能够讨论明白行盒模型之前先明白行内元素在盒子模型中的表现。进而讨论行盒模型,并且详细的说明了控制行盒模型的几个属性Line-height和vertical-align。详细介绍之前先引入一个问题,请看这个代码。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style>
		div {border: 2px solid;}
		a {	border: 1px solid;text-decoration: none;}
		a:hover{color:yellow;}
		span {
			padding: 30px;
			background-color: red;
			margin: 20px;
			border: 1px solid blue;
		}
		img {
			width: 50px;
			height: 50px;
			margin: 10px;	
		}
		.span {
			font-size: 30px;
			line-height: 100px;
		}
	</style>
</head>
<body>
	<div>
		<a href="www.baidu.com">
		<img src="maotr.png" title="maotr" alt="maotr">
		<span>x</span>
		<span class="span">x</span>
		</a>
	</div>
</body>
</html> 

你真的了解行盒模型吗?

这个代码结构在很多网站是非常流行的,一个典型的应用就是为图片和文字添加超链接。但是在这个背后却有着很多不为人知的秘密。

如果读者能够明白为什么会显示这个效果,那么没有必要再接着往下看了,或者可以以批判的眼光看看鄙人在阐述上有什么问题,否则的话还是看看吧,虽然不保证能说明白,至少可以给我提提意见吗^_^。

 


行内元素在盒模型中的表现

对于不可替代的行内元素来说,width和height这两个属性是不能描述一个不可替代的行内元素的,所以说一直都是默认值auto。

width的大小与内容的宽度有关,注意是内容的宽度,也就是说内容包含了任意的行内元素比如图片、文字等。就如前言中的例子一样,a元素的width是图片的宽度和两个span的margin、padding、border、width的和。

 

Height的大小和width就不一样了,高度仅仅与字体有关。比如还是上面这个例子,a元素的高度只是两个x中最大的那个字体大小的值与span的margin、padding没任何关系,同时高度的上边界和字体中最高的top边重合,下边界与字体中bottom边持平。

 

对于不可替代的行内元素的padding、margin、border和块元素的变现方式有很大的不同,详细来说单单不可替代的行内元素水平方向上和竖直方向上区别也不小,接下来详细的描述。

 

对于水平方向上来说,和块元素水平方向上的表现方式一样,都是占据空间的,比如上边这个例子,span和声明了margin、padding、border之后会发现都是占据空间的。

 

对于垂直方向上的来说却有差别了,垂直方向上的margin、padding、border是不占据空间的,但是唯一和块元素表现相同的是margin还是透明色,padding、border还是能够显示背景色的。同时由于对html文档的渲染是从上到下的,所以可能存在后面的行内元素的垂直方向的背景色覆盖前面的元素,对后面的元素中文字部分不会覆盖。(读者可以自行实验)这也就是为什么上面这个例子中垂直方向上的margin、padding、border对其他元素有覆盖的了。也就知道为什么a元素的高度仅仅和字体的大小有关和元素的margin、padding、border都没有关系了。


本小节就介绍完了,到此总结一下。

 行内元素在盒模型中的表现是这样的,元素的宽度与内容有关,高度仅仅与文字有关,水平方向的margin等值占据位置和块元素中表现一样,但是垂直方向上的margin等值不占据位置(也就是说占据位置仅仅是文字部分),可能导致覆盖前面的元素。

 

 

行盒模型中的行盒

值得注意的是行盒模型和行内元素的盒模型不是一个东西,行盒模型这个盒子实际是看不到的,他仅仅是由一行行内元素所确定的这么一个东西。请看这个例子:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style>
		span {
			line-height: 50px;
			border: 1px solid;
		}
	</style>
</head>
<body>
	<span>文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字	文字文字文字文字文字文字文字文字文字文字文字</span>
</body>
</html>

你真的了解行盒模型吗?

比如上图中的每一行文字虽然每一行的匿名行内元素的有自己的边框,但是每一行的行内元素组成了一个行盒模型,这个行盒模型的高度可以通过line-height来指定。但是他没有所谓的margin、padding、border等特性只是一个虚拟的框。

 

行盒模型的宽和行内元素的宽一样,与内容的宽有关,包括图片的margin、pdding、width或者是一个行内元素(span)的margin、pdding、width和。

但是行盒的高和行内元素的不一样,在默认的情况下,如果这个虚拟的行盒内部有图片的这类可替代元素,那么就是margin box的高度,如果包含不可替代的元素,那么这个高度在没有声明line-height是字体的大小(注意是字体的大小不包含margin等),否则为line-height的大小导致半行距为负。行盒的高度是最高盒子的top和最低盒子bottom的值,因为半行间距为负,可能导致行盒的大小甚至比文字的大小还小。(下一节将会讨论)

 你真的了解行盒模型吗?

 

绿色代表着虚拟的行盒,只不过在a元素内部的行盒模型和a的行盒模型完全一致。由于最高的盒子是img,所以行盒的top为img的margin box,bottom为大X下方15px处(为什么?接下来讨论行距的时候就明白了)所以说不是下方X的padding红色背景撑开的。

 

本小节就介绍完了,到此总结一下。

 

行盒模型与盒模型不同,自身是一个虚拟的盒,一行行内元素就会确定一个行盒模型。行盒模型中行盒不存在margin、border、padding属性。宽度与内容有关。高度是由不可替代元素的文字(没有margin等)可替代元素的margin box line-height值决定,盒的高度是最高盒子的top和最低盒子bottom的值。内容和行间距下一节介绍。

 

 

可能这么表述行盒模型不太清除,没关系,当接下来根据一个行盒模型图来解析行距的时候在回顾看看就会明白许多。

 

 

行盒模型中的内容与行间距

 

在行盒模型这一节中牵扯进去了有line-height,行距,半行间距这些概念,说实话,我本打算能够分开讲清楚的,但是这些之间都有着千丝万缕的联系,所以只能在后面阐述剩下的东西了,所以在看接下来的东西的时候要时不时的联想上面的内容。

 

 你真的了解行盒模型吗?

 

 

这是一个行框(行盒)的模型图并且内部仅仅有文字组成没有图片,所以可以联想有图片会是一个什么情形。上面说过,一个行盒的高度是由内部文字的大小的line-height决定的,如果内部有多个一定是由最大的那个决定。所以说和margin德国这些东西没有关系,所以从此以后将不再描述margin等值。但是line-height是个什么东西,他有什么作用?

所以接下来先介绍一下内容区域

内容区域是由一些文字组成(注意仅仅只有文字奥没有margin这些东西)的内一个文字其实三部分,一个是基线,一个是上伸部一个是下伸部分,如图所示:

 你真的了解行盒模型吗?

所以说一个内容部分的大小就是 上伸部分+下伸部分 (简写为AD)。同时也可以注意到 “字”基线下方会出一块,这就是所谓的文字下沉下过,也可以这么说,对于“X”字母的中心并不是内容的中心,由于文字下沉效果,可能会导致“X”中心点上方大于中心点下方,这也导致了一些问题。在vertical-align中这个特点表现的尤为重要。

 

接下来介绍行盒中再一个重要的概念就是基线。

上述介绍到每一个文字都有一个基线以便于确定上伸部分和下伸部分,当多个文字在一行的时候vertical-align默认值为baseline,意味着他们的基线在一条线上,所以一段文字排列整齐,多以一个可替代元素的基线是该元素margin box的下边界,所以说在文章开始的那个例子中会发现图片距离基线的位置有margin-bottom大小的间隔。

 

然后介绍行间距的概念。

行间距就是在一行文字中内容区域top和bottom之外的空间,这部分空间的大小可以有line-height决定,但是line-height的值并不是行内距的距离,他们之间满足这么一个公式。

L(行距) =  line-height - AD。所以说,L可以为负值,比如行盒模型图中“文字”部分。

L/2分别添加到内容的上边和下边就是半行间距,如黄色部分。

还要注意的是,半行距确定之后,也就是说每一个行内元素的上下边界就确定了,在第二节中说了 行盒的高度是最高盒子的top和最低盒子bottom的值,因为半行间距为负,可能导致行盒的大小甚至比文字的大小还小 。 这里的top和bottom就是相对行距确定后的边界。所以说在行盒模型图中“文字”仅仅这一部分的行盒甚至比文字大小还小。

 

本小节就介绍完了,到此总结一下。

行盒模型中的内容(可以是图片、行内元素等)仅仅和组成的每一个元素文字部分组成,内容中有基线、上伸部、下伸部分三要素,内容的高度是AD。并且文字有下沉效果。行间距大小为L(行距) =  line-height - AD。可以为负。

 

 

Line-height


特性

说明

长度值(一般以px或者em为单位)、百分数值、数字、normal、inherit

初始值

normal

应用于

所有元素(这里主要讲解行内元素和行替换元素(img))

继承性


(1)normal是默认值,但不同浏览器表现的形式可能会不一样,所以存在兼容性问题,一般不会使用normal。

(2)inherit是明确从父元素继承值,虽然line-height支持继承,但是可能存在有些元素(比如input)浏览器默认值为normal,根据css属性的层叠规则,继承而来的值没有特殊性也没有重要性,所以会被浏览器默认样式覆盖继承的样式,为了能够在父元素中使用继承而来的样式,所以可以使用这个值。

(3)长度值:比如20px,30em等是确定大小值的,可以是px固定的或者是em相对的,但是em相对是相对本元素font-size继承的值不是em,而计算后值。      
         
(4)百分数:比如20%等是通过百分数确定大小的,百分数和em一样也是相对于该元素的font-size计算值,然后将计算后的值继承给子元素。        
   
(5)数字:比如line-height:1 .是指缩放因子。  也是相对于元素的font-size计算大小。但是与em % 不同的是被继承的不是计算后的值,而是这个缩放因子,也就是说不会出现上述重叠的现象除非残设置的值小于1 

 

 

Struct空白节点的问题

 

一般情况下如果一个行盒模型内部不包含任何文字的话,特别有代表性的就是在一个行和模型中有一张图片,那么默认情况下会包含一个struct节点,只不过这个节点的宽度为0不可见,但是有高度的,同时这个空白节点可以继承自父元素的line-height属性,所以说可能影响布局。如下图所示:

 你真的了解行盒模型吗?

会发现,图片下方有一小块空白区域,本质原因是由于line-height的高度是是最高盒子的top和最低盒子bottom的值。这里的top是图片的上外边界,但是bottom是文字的下伸部分。

这个问题的根本原因就是存在这么一个看不见的但是类似文字一样的空白节点。解决这个问题有两种方式:

一、通过将在外面div中设置font-szie为0或者line-height为0.这样高度就会明显的为0.

二、第二种方式本质是使得图片和这个空白节点不会基线对齐。比如可以将img display设置为block或者将img的vestical-align:bottom。

 

 

vertical-align

 

见 http://blog.csdn.net/wmaoshu/article/details/52964251