问题
1. 在什么场景下会出现外边距合并?如何合并?如何不让相邻元素外边距合并?给个父子外边距合并的范例
外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距。合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。
外边距合并主要有 2 种典型的例子:
- 相邻元素的外边距合并
- 父子元素的外边距合并(假如“父”与“子”都在正常的文档流里面,“父”没有 border 和 padding ,那么它们之间就会产生外边距合并,取其中的最大值。)
- 自身“空元素”(无内容,无 border,无 padding)也有可能发生合并(这种情况比较特殊)
demo - 父元素与子元素的外边距合并
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父元素与子元素外边距合并</title>
<style media="screen">
* {
margin: 0;
padding: 0;
}
.container {
width: 300px;
height: 300px;
background-color: blue;
/*border: 1px solid;*/
margin: 100px;
}
.box {
width: 100px;
height: 100px;
background-color: red;
margin: 100px;
}
</style>
</head>
<body>
<div class="container">
<div class="box"></div>
</div>
</body>
</html>
父元素与子元素外边距合并1.png
可以看出,父元素的 margin-top 与子元素的 margin-top 发生合并,变为 100px。
当父元素有 border 的时候,
.container {
width: 300px;
height: 300px;
background-color: blue;
border: 1px solid;
margin: 100px;
}
父元素与子元素外边距合并2.png
当父元素添加了 border ,父元素与子元素的外边距没有合并。
demo-兄弟元素和它们的子元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>兄弟元素和它们的子元素</title>
<style media="screen">
* {
margin: 0;
padding: 0;
}
.ct1 {
width: 300px;
height: 300px;
margin-bottom: 25px;
background-color: yellow;
}
.box1 {
width: 100px;
height: 100px;
background-color: red;
margin-bottom: 100px;
}
.box2 {
width: 100px;
height: 100px;
background-color: blue;
margin-top: 100px;
margin-bottom: 200px;
}
.ct2 {
width: 300px;
height: 300px;
margin-top: 50px;
background-color: lightgreen;
}
</style>
</head>
<body>
<div class="ct1">
<div class="box1"></div>
<div class="box2"></div>
</div>
<div class="ct2"></div>
</body>
</html>
兄弟元素和它们的子元素1.png
注意:ct1 和 ct2 之间的间隔只有 50px。(各元素之间并没有“间隔”padding,border,BFC),推测:这个 “50px” 是 ct2 的。
当 ct2 的 margin-top 改为 30px 时,间隔为 30px。
兄弟元素和它们的子元素2.png当 ct2 的 margin-top 改为 10px 时,ct1 与 ct2 之间的间隔为 25px。
兄弟元素和它们的子元素3.png所以知道,ct1 与 box2 之间的下外边距为 “ct1”的。
原因:bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height
(对于margin-bottom来说,父元素高度需为auto才能和子元素合并。)
设置 height 为 auto
.ct1 {
width: 300px;
/*height: 300px;*/
margin-bottom: 25px;
background-color: yellow;
}
兄弟元素和它们的子元素4.png
ct1 和 ct2 之间的 “间隔” 为 box2 的 200px。
demo - “空元素”,高度为0并且最小高度也为0(无内容)的元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>空元素</title>
<style media="screen">
* {
margin: 0;
padding: 0;
}
.box {
background-color: red;
margin-top: 100px;
margin-bottom: 100px;
}
p {
background-color: green;
}
</style>
</head>
<body>
<div class="box"></div>
<p>testtesttesttesttesttesttesttest</p>
</body>
</html>
空元素外边距合并1.png
可以看见,.box 的上下 margin 发生合并(100px)。
当 .box 设置了 height (有数值)时,
.box {
height: 100px;
background-color: red;
margin-top: 100px;
margin-bottom: 100px;
}
空元素上下外边距合并2.png
tips:
- 当 2 个 “div” 之间没有 border、padding以及不满足 BFC 的时候,会发生外边距合并。
- 在CSS当中,相邻的 2 个盒子(可能是兄弟关系也可能是祖先关系)的外边距可以结合成一个单独的外边距。
- 外边距合并的规则
- 两个相邻的外边距都是正数时,折叠结果是它们两者之间的较大值
- 两个相邻的外边距都是负数时,折叠结果是它们绝对值的较大值两者之间的较小值(例如,一个是 -90px, 另一个是 -30px, 则取 -90px)
- 两个外边距一正一负时,折叠结果时两者相加的和
拓展阅读:
2. 去除 inline-block
内缝隙有哪几种常见的方法?
!!!!!代码之间的“间隔”会显示为这个“内缝隙”
这个“间隔”可以理解为一个“空格”,可以应用“font”。
消除 inline-block
内缝隙方法
第 1 种方法:(删除间隔)
可以直接把各行代码的间隔全部删掉(简单粗暴的方法)
第 2 种方法:(设置margin-left)
设置 margin-left: -4px;(这个 -4px 是个约定俗成的数字)然后单独为第一个元素设置 margin-left: 0px;(防止走出父容器)
第 3 种方法:(font-size: 0px;)
font-size: 0px;然后为每个“字体”单独设置各自的“font-size”
第 4 种方法:(float)
float + 清除浮动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>inline-block缝隙</title>
<style media="screen">
html,body,ul,li {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
.box {
border: 1px solid green;
overflow: auto;
/*font-size: 0;*/
}
.box>li:first-child {
/*margin-left: 0*/
}
.box>li {
display: inline-block;
/*margin-left: -4px;*/
float: left;
background-color: blue;
color: #fff;
padding: 3px;
/*font-size: 12px;*/
}
</style>
</head>
<body>
<ul class="box">
<li>tag1</li>
<li>tag2</li>
<li>tag3</li>
</ul>
<p>
dfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdf
</p>
</body>
</html>
没清除浮动的后果:
没有清除浮动.png父容器没有撑开,后面的 p
会围绕着浮动元素。
清除浮动:
已清除浮动.png3. 父容器使用 overflow: auto | hidden
撑开高度的原理是什么?
overflow
,指定如果内容溢出一个元素的框,会发生什么。
值 | 描述 |
---|---|
visible | 默认值。内容不会被修剪,会呈现在元素框之外 |
hidden | 内容会被修剪,并且其余内容是不可见的 |
scroll | 内容会被修剪,但是浏览器会显示滚动条以便查看其它的内容 |
auto | 如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容 |
inherit | 规定应该从父元素继承 overflow 属性的值 |
首先,先来看看满足 BFC 的条件:
- float 的值不是 none
- position 的值不是 static 或者 relative
- display 的值是 inline-block、table-cell、flex、table-caption、inline-flex
- overflow 的值不是 visible
所以,只要 overflow 的值不是 visible ,都能形成 BFC。
这样,就可以让容器内的元素不受外面影响。
BFC是一个名词,是一个独立的布局环境,我们可以理解为一个箱子(实际上是看不见摸不着的),箱子里面物品的摆放是不受外界的影响的。转换为BFC的理解则是:BFC中的元素的布局是不受外界的影响(我们往往利用这个特性来消除浮动元素对其非浮动的兄弟元素和其子元素带来的影响。)
拓展阅读:
4. BFC
是什么?如何形成 BFC
,有什么作用?
Block formatting contexts,块级格式化上下文。
创建了 BFC 的元素就是 1 个独立的盒子,不过只有 Block-level box 可以参与创建 BFC,它规定了内部的 Block-level box 如何布局,并且与这个独立盒子里的布局不受外部影响,当然它也不会影响到外面的元素。
BFC 是个很奇怪的东西,它一直隐式地存在CSS的样式里,但是要记住 BFC 是页面元素里一个独立存在作用块,它不影响它外面的布局,外面的元素也不会影响到 BFC 里面的布局。
定义:浮动元素和绝对定位元素,非块级盒子的块级容器(例如:inline-blocks, table-cells, table-captions),以及 overflow 值不是 “visible” 的块级盒子,都会为他们的内容创建新的 BFC (块级格式上下文)。
一个 HTML 元素要创建 BFC ,则满足下列的任意一个或多个条件即可:
- float 的值不是 none
- position 的值不是 static 或者 relative
- display 的值是 inline-block、table-cell、flex、table-caption、inline-flex
- overflow 的值不是 visible
作用:
- 撑开父元素
- 阻止外边距
- 清除浮动的文字环绕和位置的影响
BFC 是一个独立的布局环境,其中的元素布局是不受外界的影响,并且在一个 BFC 中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直地沿着其父元素的边框排列。
BFC 有以下特性:
- 内部的 Box 会在垂直方向,从顶部开始一个接一个地放置。
- Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的 2 个相邻 Box 的 margin 会发生叠加。
- 每个元素的 margin box 的左边,与包含块 border box 的左边相接触(对于从左到右的格式化,否则相反)。即使存在浮动也是如此。
- BFC 的区域不会与 float box 叠加。
- BFC 就是页面一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然。
- 计算 BFC 的高度时,浮动元素也参与计算。
拓展阅读:
5. 浮动导致的父容器高度塌陷指什么?为什么会产生?有几种解决方法
父容器里面的元素浮动-->脱离文档流,父容器自然就会高度塌陷。
这种情况,清除浮动即可。
父容器高度塌陷例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父容器高度塌陷</title>
<style media="screen">
.container {
width: 500px;
border: 1px solid red;
}
.item1 {
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
.item2 {
width: 100px;
height: 100px;
background-color: green;
float: right;
}
</style>
</head>
<body>
<div class="container">
<div class="item1"></div>
<div class="item2"></div>
</div>
</body>
</html>
父容器高度塌陷.png
清理浮动的方法
1. 清理浮动-使用带有 clear 属性的空元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>清理浮动-使用带有 clear 属性的空元素</title>
<style media="screen">
.container {
width: 500px;
border: 1px solid red;
}
.item1 {
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
.item2 {
width: 100px;
height: 100px;
background-color: green;
float: right;
}
.clear {
clear: both;
}
</style>
</head>
<body>
<div class="container">
<div class="item1"></div>
<div class="item2"></div>
<div class="clear"></div>
</div>
</body>
</html>
清理浮动-使用带有 clear 属性的空元素.png
尽管这种方法兼容所有浏览器并且随用随清,但是这会添加大量无语义的 html 元素。
2. 使用 CSS 的 :after 伪元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用CSS的 :after 伪元素</title>
<style media="screen">
.container {
width: 500px;
border: 1px solid red;
}
.item1 {
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
.item2 {
width: 100px;
height: 100px;
background-color: green;
float: right;
}
.container:after {
content: '';
display: block;
clear: both;
}
</style>
</head>
<body>
<div class="container">
<div class="item1"></div>
<div class="item2"></div>
</div>
</body>
</html>
CSS-after清除浮动.png
父容器添加一个看不见的块元素( :after )来清理浮动。
需要注意的是,为了兼容 IE6 和 IE7,要添加一条 zoom:1; 来触发 haslayout (可以写到 IE6 和 IE7 的 CSS hacker 文件里,这样不会影响 W3C 标准验证。)
这种方法需要给每组浮动元素都添加一个容器,推荐在页面布局时使用。大量使用依然会对代码量造成一些影响。
3. 使用 CSS 的 overflow 属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用 CSS 的 overflow 属性进行怪异处理</title>
<style media="screen">
.container {
width: 500px;
border: 1px solid red;
/*overflow: hidden;*/
overflow: auto;
}
.item1 {
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
.item2 {
width: 100px;
height: 100px;
background-color: green;
float: right;
}
</style>
</head>
<body>
<div class="container">
<div class="item1"></div>
<div class="item2"></div>
</div>
</body>
</html>
使用 overflow 属性.png
虽然很多地方以“将来浏览器可能不兼容”为由,不建议使用这个方法。但是短时间内浏览器不会在这个问题上后退处理。另外,这个方法无需添加额外的 class ,在做主题时比较实用。建议,在局部和无法添加 class a 的地方使用该方法清理浮动,但不要作为主要清理浮动方式。 overflow: auto; 还是不要用了。
4. 给浮动元素的容器添加浮动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>给浮动元素的容器添加浮动</title>
<style media="screen">
.container {
width: 500px;
border: 1px solid red;
float: left;
}
.item1 {
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
.item2 {
width: 100px;
height: 100px;
background-color: green;
float: right;
}
</style>
</head>
<body>
<div class="container">
<div class="item1"></div>
<div class="item2"></div>
</div>
</body>
</html>
给浮动元素的容器添加浮动.png
给浮动元素的容器添加浮动属性也可清除内部浮动。但是这会对接下来的文档造成影响。
建议,在容器原本就浮动,或者容器使用了绝对定位时使用这个方法。不要在主要布局中使用。
5. 使用邻接元素清理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用邻接元素清理</title>
<style media="screen">
.container {
width: 500px;
border: 1px solid red;
}
.item1 {
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
.item2 {
width: 100px;
height: 100px;
background-color: green;
float: right;
}
.content {
clear: both;
}
</style>
</head>
<body>
<div class="container">
<div class="item1"></div>
<div class="item2"></div>
<div class="content"></div>
</div>
</body>
</html>
使用邻接元素清理.png
给浮动元素后面的元素添加 clear 属性。
要确保后面的元素与浮动元素同在一个容器(.container)内。
如果 .content 在 .container 后面,建议使用 :after 伪元素清理。
总结:
在网页主要布局中,使用 :after 伪元素作为主要清理浮动方式。
在小模块( ul )使用 overflow: hidden; (留意可能产生的隐藏溢出元素问题。
如果本身就是浮动元素则可自动清除内部浮动,无需额外处理。
正文中,使用邻接元素清理之前的浮动。
需要熟悉各种清理方式的原理和利弊。
拓展阅读:
6. 以下代码每一行的作用是什么?为什么会产生作用?和 BFC 撑开空间有什么区别?
.clearfix:after{
content: '';
display: block;
clear: both;
}
.clearfix{
*zoom: 1;
}
/* 这段代码用于普通浏览器清除浮动 */
.clearfix:after{ /* :after 伪元素清理浮动 */
content: ''; /* 在后面添加一个“空”的内容 */
display: block; /* 设置这个“空”的内容为块级元素 */
clear: both; /* 这个”空“的内容左右两边不能有浮动元素 */
}
/* 用于 IE 浏览器清除浮动 */
.clearfix{ /* class 属性为 clearfix 的元素 */
*zoom: 1; /* 设置缩放比例为 1 ,这是 IE 专有属性。*/
}
第一段代码:在父容器后面加一个“空”元素,令这个“空”元素左右不能有浮动元素。然后这个“空”元素就会下移,这样就撑开了父元素。
第二段代码:zoom: 1; 缩放页面,重新排版,父元素重新计算浮动元素的高度。父容器就因此撑开了。
网友评论