盒模型、浮动和定位是CSS中最重要的三个概念。它们共同决定了一个元素在页面中以怎样的形式进行排布与显示。
一、盒模型
1. 定义
盒模型是CSS的核心概念。一个页面中,所有的元素(不管他最终显示是圆形、矩形还是三角形)都被看作一个矩形盒子,这个盒子包含了内容区、内边距、边框和外边距。
图1. CSS盒模型
我们可以把它想象成现实世界中网购的快递盒子,外边距就是这个盒子离其他盒子的距离,边框就是这个盒子的材料,内边距就是内层缓震的泡沫,而内容区自然就是你网购的物品。但难以理解的是CSS的盒模型与现实生活中的快递盒子对宽高的定义不同。人对快递盒子的宽高定义包括了盒子材料本身,而在CSS中,盒模型的width和height属性描述的是内容区的宽高,不包括内边距和边框。只要理解了盒模型与现实生活中盒子的联系与区别,那么盒模型很快就能为我们所用。
2. 属性
以上提出这个问题我们也可以通过定义一个盒子的box-sizing属性来解决。box-sizing默认为content-box,可以修改为border-box来保证CSS中的盒模型width和height也把内边距和边框包含进来。这种计算宽高的方式比原来更加直观,因为它更贴近现实生活。
还有一个问题是属性大小的百分比定义。因为编写CSS代码时,高度属性一般不会定义,而通过内容的多少来自适应规定高度(保证了内容不会无端消失)。因此,除了高度的百分比与包含盒子的高度有关以外,其他的长度使用百分比都根据包含盒子的宽度来计算(包括垂直方向上的padding-top、padding-bottom、margin-top和margin-bottom)。
3. 包含盒子
补充以上的概念,什么是包含盒子?当定义像 position: absolute 这种使盒子脱离文档流的属性以后,包含盒子就变成了 <html></html> ,其他状态下,包含盒子都为直接的父元素。
二、可见的格式化模型
了解了盒模型以后,我们可以来观察如何来格式化和定位一个盒模型了。我们常提到“块级元素”“行级元素”,实际上是这些元素以“块盒子”和“行内盒子”的模型存在,通过调整display属性可以切换一个元素是行级还是块级。块盒子沿垂直方向堆叠;行盒子沿水平方向堆叠,不够位置了才换行。我们都知道块盒子可以自由设置宽高,行内盒子设置宽高无效。同时,比如我们在HTML中写入的有实际内容的文字也会组成DOM节点(像 <strong>、<em> 这种标签也同样),它们是“行盒子”,只能通过line-height属性来调整高度。总而言之,我们只需要关注①块盒子的宽高可自由定义;②行内盒子的宽高无效;③行盒子只能定义“line-height”调整高度,这三点基础就足够了。
三、margin塌陷(margin折叠)
常规的盒子中有一种机制是margin折叠,这经常给我们布局网页带来困扰:在垂直方向上,两个外边距相遇时,会折叠成两个中较大的一个外边距(外部盒子与内部盒子的外边距也同样会折叠)。遇到这种情况怎么解决呢,答案是用一些黑客写法:定义一个细小的透明border,它的属性为 border: 1px solid transparent; ,这样肉眼看不出,外边距也不会折叠到一起。又或者直接使用padding取代margin,不会产生折叠。
四、浮动
浮动会使盒子脱离正常的文档流,但它被设计出来的目的原本是为了让文本可以环绕图片,因此跟 position: absolute 它们又有些许差别。
五、浮动闭合清除原理
由于浮动的元素不会在文档中占有位置,因此它的高度不会把装载它的(不是浮动盒子的)父盒子撑开。有时候我们需要阻止行盒子环绕在浮动盒子外面,CSS为我们提供了clear属性。它的值有left、right、both和none,用来指定这个行盒子的哪一侧不能紧挨着浮动盒子。因此要想清除浮动闭合,我们又可以用一个黑客写法,利用一个空div,设置它的clear为both,这样这个空的div就左右两侧都不会贴着这个浮动的盒子。同时,设置这个div为 display: block ,这个空div的宽度是默认和父盒子同样宽的,因此它会紧贴在浮动盒子的下方。由于这个div是在文档中占有空间的,因此父盒子就会被撑开。具体的代码如下:
1 .outer { 2 border: 1px solid black; 3 } 4 5 .inner1 { 6 float: left; 7 background: greenyellow; 8 width: 50px; 9 height: 30px; 10 } 11 12 .outer::after { 13 content: ''; 14 display: block; 15 clear: both; 16 }
1 <div class="outer"> 2 <div class="inner1"> 3 Hello world 4 </div> 5 </div>
六、其他新式CSS布局模块
1. 弹性盒子布局模块(Flexible Box Layout Module)
Flexbox是它的简称,它支持对子元素水平垂直布局,可以设置子元素的大小、间距和对齐方式,此外可以调整使子元素渲染到页面的顺序跟HTML顺序不同。
2. 网格布局模块(Grid Layout)
网格布局实现了源代码次序的完全分离,从内容结构和个别模块的表现中抽象出网格系统。网格系统的目标是取代落后的浮动和定位元素布局方式。
3. 多栏布局(Multi-column Layout Module)
多栏布局可以实现我们常提到的“瀑布流”,浏览器会自动根据可用宽度进行调整。
总结:我们介绍了盒模型,内外边距、宽高会如何影响盒子的大小,了解了块盒子、行盒子、行内盒子、浮动盒子等区别。我们还学习了如何解决margin塌陷的问题,懂得了清除浮动闭合的原理。