【CSS学习(三)盒子模型、边距重叠 & 浮动、清除浮动】
盒子模型
盒子模型在CSS学习中尤为重要,对盒子模型的深刻理解有利于 CSS开发水平的提示,在开发中遇到难以理解的现象,往往是因为对模型的理解不够。
盒子模型这个名词来自英文里面的Box modelmodel。怎么理解盒子模型呢?我认为凡是里面可以盛装其他内容的标签,我们都可以称之为盒子。例如:div,p,span等等标签都可以往里面再添加元素,我们都可以称之为盒子模型,相反例如img,input等等 里面是无法盛装其他元素,我们就能称之为盒子。
盒子模型的构成
标准的盒子模型一般由外边距区域、边框区域、内边距区域、和内容构成。
我们随便点开一个网页按下 F12,都能看到盒子模型的身影。
我们在盒子模型中能够看到这么几个属性
-
margin:用空白区域扩展边框区域,来分开相邻的元素,也就是外边距
-
border:边框
-
padding:内容与边框之间的距离,也就是我们所说的内边距
-
content:可以放置元素的区域,如文本图像等,一般设置宽高度指的是这个内容的宽高;
我们先从边框入手
边框
边框使用 border
属性定义,该属性需要我们手动的为其添加三个参数。
这三个参数的分别是边框的粗细、样式、颜色。
border: 1px solid red;
空元素的边框默认是这样的
我们从尝试向 div标签中添加文本内容
<div class="box">
我是文本内容
</div>
有文本内容后,边框会将文本内容包裹
由于 div标签是块级元素,它的宽度默认是%100。所以会出现这种边框占满一行的情况
我们可以通过修改 div标签的宽来使边框达到一个比较理想的效果。
.box{
width: 100px;
border: 1px solid red;
}
boder属性第二个参数的修改,能够改变边框的样式。
能够修改的样式非常之多,感兴趣的朋友可以慢慢尝试
关于边框的更多操作可以移步该文章
外边距
我们仔细观察黑箭头指向的地方,发现边框并没有和网页贴合。
边框和网页之间存在一定的间隙,至于为什么会产生间隙我相信有认真看上文的朋友应该已经猜到了。
这个间隙就是我们的外边距区域,设置外边距会在元素外创建额外的“空白”。
设置外边距的最简单的方法就是使用 margin属性,这个属性接受任何长度单位、百分数值甚至负值。
有些标签存在一个 margin
属性的默认值,比如我们包裹 div标签的 body标签。
我们按下 F12,选中 body标签。
发现body标签确实存在一个默认的外边距,该外边距的值为 8px
我们只需要将该外边距的值清空就能实现边框与网页贴合的效果
body{
margin: 0;
}
我们从上面 body的盒子模型中可以看出来,外边距是分上下左右的。
我们如果在 margin
属性中 只添加一个长度单位作为参数,那么该参数默认为上下左右四个外边距的参数。
这也就是为什么,我们要将四个方向的外边距都清空只需要指定一个长度单位参数的原因。
那能不能分别指定上下左右四个方向的外边距的参数值呢?
那自然是可以的
如果我们指定两个参数,那么第一个参数默认为上下外边距的参数 第二个参数则是左右外边距的参数。
margin: 100px 200px;
如果我们指定四个参数,那么这四个参数 分别对应上右下左四个位置的外边距参数
margin: 100px 200px 300px 400px;
实际上就是一个顺时针的顺序,并不会按什么上下左右来排。
外边距还有一个妙用,它能够使我们的元素水平居中
该操作对元素有一定的要求,首先需要该元素为块元素 其次宽度需要是固定的
margin: 0 auto;
除了使用 margin
属性统一来定义四个外边距的参数,我们还可以使用以下四个属性来分别指定。
margin-top: 100px;
margin-right: 200px;
margin-bottom: 300px;
margin-left: 400px;
效果是一样的。
内边距
内边距是内容和边框之间的距离,上面关于外边距的操作放到内边距中大多都适用。
padding: 100px 200px 300px 400px;
或者
padding-top: 100px;
padding-right: 200px;
padding-bottom: 300px;
padding-left: 400px;
标准模型和IE模型的区别
标准模型指的是设置box-sizing为content-box的盒子模型,一般width,height 指的是content的宽高。
而IE模型指的是box-sizing为border-box的盒子模型。宽高的计算是content + padding + border;
默认的盒子模型为标准模型,也就是box-sizing: content-box;
而设置IE模型我们需要将 content-box修改为 border-box
边距重叠
边距重叠(塌陷)是指两个或多个盒子(可能相邻也可能嵌套)的相邻边界(其间没有任何非空内容、补白、边框)重合在一起而形成一个单一边界。
父子元素的边距重叠
首先说明一下什么情况下父子元素之间会发生边距重叠,现在考虑父元素中包含一个子元素的情况,当子元素设置了 margin,父元素的 border,padding 为 0 的情况下才会发生边距重叠。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.parent {
background: #e7a1c5;
}
.parent .child {
background: #c8cdf5;
height: 100px;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">
</div>
</div>
</body>
</html>
从上面的代码中可以看到,我们的 div标签并未定义 border和padding
属性,且不存在一个默认的值。
那么应该就会出现我们所说的边距重叠的问题
原因也说过了,如果块元素的 margin-top
与它的第一个子元素的 margin-top
之间没有 border
、padding
来分隔,或者块元素的 margin-bottom 与它的最后一个子元素的 margin-bottom 之间没有 border
、padding
分隔,那么外边距会塌陷。子元素多余的外边距会被父元素的外边距截断。
我们尝试定义一个border,看看能否解决边距重叠的问题
border: 1px solid red;
确实能够解决该问题,也就是说我们只要使父子元素之间隔一层就好了。
当我们父子元素都定义了 marine-top时,会取较大的 margin-top 值。
.parent {
background: #e7a1c5;
margin-top: 60px;
}
.parent .child {
background: #c8cdf5;
height: 100px;
margin-top: 100px;
}
相邻元素的边距重叠
我们一般说的外边距塌陷实际上不是上面这种情况。
而是像这种情况
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.blue{
background: blue;
height: 20px;
margin-bottom: 110px;
}
.parent {
background: #e7a1c5;
margin-top: 60px;
}
.parent .child {
background: #c8cdf5;
height: 100px;
margin-top: 100px;
}
</style>
</head>
<body>
<div class="blue"></div>
<div class="parent">
<div class="child">
</div>
</div>
</body>
</html>
我们在父元素上再定义一个元素,该元素的 marine-bottom如果 大于等于父子元素边距重叠后最终取得的 margin-top 的值时,父子元素的 margin-top 就不起作用了,这就是我们常说的外边距塌陷。
空元素的边界重叠
如果我们定义一个空元素,该元素有外边距,但是没有边框或者填充 那么上下边距会碰到一起,二者会合并。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<style>
.box{
margin-top: 20px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="box">
</div>
</body>
</html>
防止垂直 margin 重叠
解决上述问题的其中一个办法就是创建 BFC。BFC 的全称为 Block Formatting Context
,即块级格式化上下文。
- 处于同一个 BFC 中的元素相互影响,可能会发生 margin collapse;
- BFC 在页面上是一个独立的容器,容器里面的子元素不会影响到外面的元素,反之亦然;
- 计算 BFC 的高度时,考虑 BFC 所包含的所有元素,包括浮动元素也参与计算;
- 浮动盒的区域不会叠加到 BFC 上;
也就是说,我们只需要在父元素或者相邻元素中加入一个overflow: hidden;
即可。
浮动
在css中,存在块级元素和内联(行内)元素两种元素。
块级元素会单独占一行而内联元素会与之前的内容保持显示在同一行。
一般定义块级元素会使用 div内联元素则使用 span
块级元素中可以包含内联元素,反之不行。
<div class="div1">
块级
</div>
<div class="div2">
元素
</div>
<span class="span1">
内联
</span>
<span class="span2">
元素
</span>
我们在日常生活中打开的一个一个网页,能够发现它并不像我们写的 HTML那样自上而下是一个标准的文档流布局。
该网页中,多个块级元素被放到了同一行内。这种效果我们可以通过浮动来实现
float
float元素也称为浮动元素,设置了 float属性的元素会根据属性值向左或向右浮动。浮动元素会从普通文档流中脱离,但浮动元素影响的不仅是自己,它会影响周围的元素对齐进行环绕。简单来说,就是让 block元素无视 float元素,让 inline元素让流水一样围绕着 float元素来实现浮动布局。如下所示:
浮动的特性
不管一个元素是行内元素还是块级元素,如果被设置了浮动,那浮动元素会生成一个块级框,可以设置它的width和height,因此float常常用于制作横向配列的菜单,可以设置大小并且横向排列。
文字环绕图片是float典型的应用场景,img元素设置了float:left
之后会脱离文档流而居于左侧存在。而p元素无视img元素的存在,从窗口的左上角开始流入,但是p元素中的文字意识到img元素的存在而环绕图片流入。并且img元素是漂浮在p元素的上层。
<body>
<div class="div1">
<img src="../../resources/image/5.jpg" >
</div>
<p>
文字环绕图片是float典型的应用场景,img元素设置了float:left之后会脱离文档流而居于左侧存在。
--------------------------------------------------------------------------
--------------------------------------------------------------------------
而p元素无视img元素的存在,从窗口的左上角开始流入,但是p元素中的文字意识到img元素的存在而环绕图片流入。
--------------------------------------------------------------------------
--------------------------------------------------------------------------
并且img元素是漂浮在p元素的上层。
--------------------------------------------------------------------------
--------------------------------------------------------------------------
</p>
</body>
div{
float: left;
}
如何理解img元素是漂浮在p元素的上层(脱离了普通流)
脱离普通流是指:他的父容器在去计算宽高的时候,发现不了浮动元素。即,父容器不会被里面的浮动元素撑开;
我们为body标签添加边框,将网页的比例缩放会正常的比例(之前为了展示有将网页的比例缩小)
如果这样还看不出来的话,我们再为该 img属性添加一个内边距和边框
div{
float: left;
border: 5px solid #8d8b8b;
padding: 10px;
}
这样透过内边距底下的 红色body边框,应该更能理解什么叫img元素是漂浮在p元素的上层的这一概念。
再无法理解就为body添加背景颜色吧.....
默认情况下,块级元素的宽是100%,一旦让块级元素浮动起来,立刻会像行内元素一样产生包裹性,宽度会跟随内容自适应。
也就是说,如果我们的网页放不下这么多浮动在同一行的块级元素,多出来的块级元素就会换到下一行。
我们将上面的 img元素多复制几份,看看是否如此。
我们将网页缩放
确实是如此
还有一个卡住的情况
我们将原本复制的img元素删掉一部分,为剩下的三个img元素添加不同颜色的边框和左浮动。
为第一个img元素添加高这一属性,该属性的值大于图片本身的高。
.div1{
height: 250px;
float: left;
border: 5px solid #64b373;
}
.div2{
float: left;
border: 5px solid #4c4cf8;
}
.div3{
float: left;
border: 5px solid #f1f168;
}
在网页上显示的效果如上,如果这个时候我们将网页缩放,使黄色边框的img元素去到下一行。
按正常的思维,黄色边框的img元素应该会去到绿色边框img元素的底下,但实际并不是这样的
确认:
站在浏览器的角度,从上往下渲染文档。
当依次渲染完绿色和蓝色边框的img元素后,再渲染黄色img元素时右边放不下了。
去到下一行时它贴着蓝色边框img元素的下边缘开始向左移动,当移动碰到绿色边框img元素的下角时,动不了了被卡住了。
所以我们在设置高度不一样时,会出现一个 “卡住” 的情况。
清除浮动
通过上面的一些特性介绍,我相信大家应该都明白 浮动并不是在任何地方都适用。
因为浮动的特性 我们在开发中难免会遇到事与愿违的情况,比如父容器高度坍塌、布局随着网页的缩放而混乱…
所以在有些时候我们需要清除浮动
Clear属性
该属性提供了一些值供我们调用
-
none
- 元素不会向下移动清除之前的浮动。
-
left
- 元素被向下移动用于清除之前的左浮动。
-
right
- 元素被向下移动用于清除之前的右浮动。
-
both
- 元素被向下移动用于清除之前的左右浮动。
-
inline-start
- 该关键字表示该元素向下移动以清除其包含块的起始侧上的浮动。即在某个区域的左侧浮动或右侧浮动。
-
inline-end
- 该关键字表示该元素向下移动以清除其包含块的末端的浮点,即在某个区域的右侧浮动或左侧浮动。
清除浮动的方式有很多,我们可以在浮动元素中添加clear属性。
<div class="clear" style="clear: both"></div>
未添加clear属性前:
添加后:
使用 clear清除浮动后,它会保持块级元素和浮动的效果,即它会同块元素一样单独占一列 也会同浮动元素一样不撑开父元素。
Overflow
给浮动元素的容器添加overflow:hidden;或overflow:auto;可以清除浮动,另外在 IE6 中还需要触发 hasLayout ,例如为父元素设置容器宽高或设置 zoom:1。在添加overflow属性后,浮动元素又回到了容器层,把容器高度撑起,达到了清理浮动的效果。
为容器也添加浮动
给浮动元素的容器也添加上浮动属性即可清除内部浮动,但是这样会使其整体浮动,影响布局,不推荐使用
添加空元素
我们还可以在浮动元素的后面添加一个空元素,为该空元素添加一个 clear属性。
这样也能够起到清除浮动的效果,但并不推荐如此,因为什么呢 因为麻烦。
使用伪元素
s使用 :after 伪元素(注意这不是伪类,而是伪元素,代表一个元素之后最近的元素)我们可以实现在元素末尾添加一个看不见的块元素(Block element)。这样也能清理浮动。
可以看到,伪元素的位置在最下方了,距顶部的高度为float元素的高度,顺带撑起了父元素的高度。
放松一下眼睛
夹带私货(不是