問題
1. 在什么場景下會出現(xiàn)外邊距合并?如何合并?如何不讓相鄰元素外邊距合并?給個(gè)父子外邊距合并的范例
外邊距合并指的是,當(dāng)兩個(gè)垂直外邊距相遇時(shí),它們將形成一個(gè)外邊距。合并后的外邊距的高度等于兩個(gè)發(fā)生合并的外邊距的高度中的較大者。
外邊距合并主要有 2 種典型的例子:
- 相鄰元素的外邊距合并
- 父子元素的外邊距合并(假如“父”與“子”都在正常的文檔流里面,“父”沒有 border 和 padding ,那么它們之間就會產(chǎn)生外邊距合并,取其中的最大值。)
- 自身“空元素”(無內(nèi)容,無 border,無 padding)也有可能發(fā)生合并(這種情況比較特殊)
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>
可以看出,父元素的 margin-top 與子元素的 margin-top 發(fā)生合并,變?yōu)?100px。
當(dāng)父元素有 border 的時(shí)候,
.container {
width: 300px;
height: 300px;
background-color: blue;
border: 1px solid;
margin: 100px;
}
當(dāng)父元素添加了 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>
注意:ct1 和 ct2 之間的間隔只有 50px。(各元素之間并沒有“間隔”padding,border,BFC),推測:這個(gè) “50px” 是 ct2 的。
當(dāng) ct2 的 margin-top 改為 30px 時(shí),間隔為 30px。
當(dāng) ct2 的 margin-top 改為 10px 時(shí),ct1 與 ct2 之間的間隔為 25px。
所以知道,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才能和子元素合并。)
設(shè)置 height 為 auto
.ct1 {
width: 300px;
/*height: 300px;*/
margin-bottom: 25px;
background-color: yellow;
}
ct1 和 ct2 之間的 “間隔” 為 box2 的 200px。
demo - “空元素”,高度為0并且最小高度也為0(無內(nèi)容)的元素
<!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>
可以看見,.box 的上下 margin 發(fā)生合并(100px)。
當(dāng) .box 設(shè)置了 height (有數(shù)值)時(shí),
.box {
height: 100px;
background-color: red;
margin-top: 100px;
margin-bottom: 100px;
}
tips:
- 當(dāng) 2 個(gè) “div” 之間沒有 border、padding以及不滿足 BFC 的時(shí)候,會發(fā)生外邊距合并。
- 在CSS當(dāng)中,相鄰的 2 個(gè)盒子(可能是兄弟關(guān)系也可能是祖先關(guān)系)的外邊距可以結(jié)合成一個(gè)單獨(dú)的外邊距。
- 外邊距合并的規(guī)則
- 兩個(gè)相鄰的外邊距都是正數(shù)時(shí),折疊結(jié)果是它們兩者之間的較大值
- 兩個(gè)相鄰的外邊距都是負(fù)數(shù)時(shí),折疊結(jié)果是它們絕對值的較大值兩者之間的較小值(例如,一個(gè)是 -90px, 另一個(gè)是 -30px, 則取 -90px)
- 兩個(gè)外邊距一正一負(fù)時(shí),折疊結(jié)果時(shí)兩者相加的和
拓展閱讀:
2. 去除 inline-block
內(nèi)縫隙有哪幾種常見的方法?
!!!!!代碼之間的“間隔”會顯示為這個(gè)“內(nèi)縫隙”
這個(gè)“間隔”可以理解為一個(gè)“空格”,可以應(yīng)用“font”。
消除 inline-block
內(nèi)縫隙方法
第 1 種方法:(刪除間隔)
可以直接把各行代碼的間隔全部刪掉(簡單粗暴的方法)
第 2 種方法:(設(shè)置margin-left)
設(shè)置 margin-left: -4px;(這個(gè) -4px 是個(gè)約定俗成的數(shù)字)然后單獨(dú)為第一個(gè)元素設(shè)置 margin-left: 0px;(防止走出父容器)
第 3 種方法:(font-size: 0px;)
font-size: 0px;然后為每個(gè)“字體”單獨(dú)設(shè)置各自的“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>
沒清除浮動的后果:
父容器沒有撐開,后面的 p
會圍繞著浮動元素。
清除浮動:
3. 父容器使用 overflow: auto | hidden
撐開高度的原理是什么?
overflow
,指定如果內(nèi)容溢出一個(gè)元素的框,會發(fā)生什么。
值 | 描述 |
---|---|
visible | 默認(rèn)值。內(nèi)容不會被修剪,會呈現(xiàn)在元素框之外 |
hidden | 內(nèi)容會被修剪,并且其余內(nèi)容是不可見的 |
scroll | 內(nèi)容會被修剪,但是瀏覽器會顯示滾動條以便查看其它的內(nèi)容 |
auto | 如果內(nèi)容被修剪,則瀏覽器會顯示滾動條以便查看其余的內(nèi)容 |
inherit | 規(guī)定應(yīng)該從父元素繼承 overflow 屬性的值 |
首先,先來看看滿足 BFC 的條件:
- float 的值不是 none
- position 的值不是 static 或者 relative
- display 的值是 inline-block、table-cell、flex、table-caption、inline-flex
- overflow 的值不是 visible
所以,只要 overflow 的值不是 visible ,都能形成 BFC。
這樣,就可以讓容器內(nèi)的元素不受外面影響。
BFC是一個(gè)名詞,是一個(gè)獨(dú)立的布局環(huán)境,我們可以理解為一個(gè)箱子(實(shí)際上是看不見摸不著的),箱子里面物品的擺放是不受外界的影響的。轉(zhuǎn)換為BFC的理解則是:BFC中的元素的布局是不受外界的影響(我們往往利用這個(gè)特性來消除浮動元素對其非浮動的兄弟元素和其子元素帶來的影響。)
拓展閱讀:
4. BFC
是什么?如何形成 BFC
,有什么作用?
Block formatting contexts,塊級格式化上下文。
創(chuàng)建了 BFC 的元素就是 1 個(gè)獨(dú)立的盒子,不過只有 Block-level box 可以參與創(chuàng)建 BFC,它規(guī)定了內(nèi)部的 Block-level box 如何布局,并且與這個(gè)獨(dú)立盒子里的布局不受外部影響,當(dāng)然它也不會影響到外面的元素。
BFC 是個(gè)很奇怪的東西,它一直隱式地存在CSS的樣式里,但是要記住 BFC 是頁面元素里一個(gè)獨(dú)立存在作用塊,它不影響它外面的布局,外面的元素也不會影響到 BFC 里面的布局。
定義:浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如:inline-blocks, table-cells, table-captions),以及 overflow 值不是 “visible” 的塊級盒子,都會為他們的內(nèi)容創(chuàng)建新的 BFC (塊級格式上下文)。
一個(gè) HTML 元素要創(chuàng)建 BFC ,則滿足下列的任意一個(gè)或多個(gè)條件即可:
- float 的值不是 none
- position 的值不是 static 或者 relative
- display 的值是 inline-block、table-cell、flex、table-caption、inline-flex
- overflow 的值不是 visible
作用:
- 撐開父元素
- 阻止外邊距
- 清除浮動的文字環(huán)繞和位置的影響
BFC 是一個(gè)獨(dú)立的布局環(huán)境,其中的元素布局是不受外界的影響,并且在一個(gè) BFC 中,塊盒與行盒(行盒由一行中所有的內(nèi)聯(lián)元素所組成)都會垂直地沿著其父元素的邊框排列。
BFC 有以下特性:
- 內(nèi)部的 Box 會在垂直方向,從頂部開始一個(gè)接一個(gè)地放置。
- Box 垂直方向的距離由 margin 決定。屬于同一個(gè) BFC 的 2 個(gè)相鄰 Box 的 margin 會發(fā)生疊加。
- 每個(gè)元素的 margin box 的左邊,與包含塊 border box 的左邊相接觸(對于從左到右的格式化,否則相反)。即使存在浮動也是如此。
- BFC 的區(qū)域不會與 float box 疊加。
- BFC 就是頁面一個(gè)隔離的獨(dú)立容器,容器里面的子元素不會影響到外面的元素,反之亦然。
- 計(jì)算 BFC 的高度時(shí),浮動元素也參與計(jì)算。
拓展閱讀:
5. 浮動導(dǎo)致的父容器高度塌陷指什么?為什么會產(chǎn)生?有幾種解決方法
父容器里面的元素浮動-->脫離文檔流,父容器自然就會高度塌陷。
這種情況,清除浮動即可。
父容器高度塌陷例子:
<!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>
清理浮動的方法
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>
盡管這種方法兼容所有瀏覽器并且隨用隨清,但是這會添加大量無語義的 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>
父容器添加一個(gè)看不見的塊元素( :after )來清理浮動。
需要注意的是,為了兼容 IE6 和 IE7,要添加一條 zoom:1; 來觸發(fā) haslayout (可以寫到 IE6 和 IE7 的 CSS hacker 文件里,這樣不會影響 W3C 標(biāo)準(zhǔn)驗(yàn)證。)
這種方法需要給每組浮動元素都添加一個(gè)容器,推薦在頁面布局時(shí)使用。大量使用依然會對代碼量造成一些影響。
3. 使用 CSS 的 overflow 屬性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用 CSS 的 overflow 屬性進(jìn)行怪異處理</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>
雖然很多地方以“將來瀏覽器可能不兼容”為由,不建議使用這個(gè)方法。但是短時(shí)間內(nèi)瀏覽器不會在這個(gè)問題上后退處理。另外,這個(gè)方法無需添加額外的 class ,在做主題時(shí)比較實(shí)用。建議,在局部和無法添加 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>
給浮動元素的容器添加浮動屬性也可清除內(nèi)部浮動。但是這會對接下來的文檔造成影響。
建議,在容器原本就浮動,或者容器使用了絕對定位時(shí)使用這個(gè)方法。不要在主要布局中使用。
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>
給浮動元素后面的元素添加 clear 屬性。
要確保后面的元素與浮動元素同在一個(gè)容器(.container)內(nèi)。
如果 .content 在 .container 后面,建議使用 :after 偽元素清理。
總結(jié):
在網(wǎng)頁主要布局中,使用 :after 偽元素作為主要清理浮動方式。
在小模塊( ul )使用 overflow: hidden; (留意可能產(chǎn)生的隱藏溢出元素問題。
如果本身就是浮動元素則可自動清除內(nèi)部浮動,無需額外處理。
正文中,使用鄰接元素清理之前的浮動。
需要熟悉各種清理方式的原理和利弊。
拓展閱讀:
6. 以下代碼每一行的作用是什么?為什么會產(chǎn)生作用?和 BFC 撐開空間有什么區(qū)別?
.clearfix:after{
content: '';
display: block;
clear: both;
}
.clearfix{
*zoom: 1;
}
/* 這段代碼用于普通瀏覽器清除浮動 */
.clearfix:after{ /* :after 偽元素清理浮動 */
content: ''; /* 在后面添加一個(gè)“空”的內(nèi)容 */
display: block; /* 設(shè)置這個(gè)“空”的內(nèi)容為塊級元素 */
clear: both; /* 這個(gè)”空“的內(nèi)容左右兩邊不能有浮動元素 */
}
/* 用于 IE 瀏覽器清除浮動 */
.clearfix{ /* class 屬性為 clearfix 的元素 */
*zoom: 1; /* 設(shè)置縮放比例為 1 ,這是 IE 專有屬性。*/
}
第一段代碼:在父容器后面加一個(gè)“空”元素,令這個(gè)“空”元素左右不能有浮動元素。然后這個(gè)“空”元素就會下移,這樣就撐開了父元素。
第二段代碼:zoom: 1; 縮放頁面,重新排版,父元素重新計(jì)算浮動元素的高度。父容器就因此撐開了。