問題
1. 在什么場景下會出現外邊距合并?如何合并?如何不讓相鄰元素外邊距合并?給個父子外邊距合并的范例
外邊距合并指的是,當兩個垂直外邊距相遇時,它們將形成一個外邊距。合并后的外邊距的高度等于兩個發(fā)生合并的外邊距的高度中的較大者。
外邊距合并主要有 2 種典型的例子:
- 相鄰元素的外邊距合并
- 父子元素的外邊距合并(假如“父”與“子”都在正常的文檔流里面,“父”沒有 border 和 padding ,那么它們之間就會產生外邊距合并,取其中的最大值。)
- 自身“空元素”(無內容,無 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。
當父元素有 border 的時候,
.container {
width: 300px;
height: 300px;
background-color: blue;
border: 1px solid;
margin: 100px;
}
當父元素添加了 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),推測:這個 “50px” 是 ct2 的。
當 ct2 的 margin-top 改為 30px 時,間隔為 30px。
當 ct2 的 margin-top 改為 10px 時,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才能和子元素合并。)
設置 height 為 auto
.ct1 {
width: 300px;
/*height: 300px;*/
margin-bottom: 25px;
background-color: yellow;
}
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>
可以看見,.box 的上下 margin 發(fā)生合并(100px)。
當 .box 設置了 height (有數值)時,
.box {
height: 100px;
background-color: red;
margin-top: 100px;
margin-bottom: 100px;
}
tips:
- 當 2 個 “div” 之間沒有 border、padding以及不滿足 BFC 的時候,會發(fā)生外邊距合并。
- 在CSS當中,相鄰的 2 個盒子(可能是兄弟關系也可能是祖先關系)的外邊距可以結合成一個單獨的外邊距。
- 外邊距合并的規(guī)則
- 兩個相鄰的外邊距都是正數時,折疊結果是它們兩者之間的較大值
- 兩個相鄰的外邊距都是負數時,折疊結果是它們絕對值的較大值兩者之間的較小值(例如,一個是 -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>
沒清除浮動的后果:
父容器沒有撐開,后面的 p
會圍繞著浮動元素。
清除浮動:
3. 父容器使用 overflow: auto | hidden
撐開高度的原理是什么?
overflow
,指定如果內容溢出一個元素的框,會發(fā)生什么。
值 | 描述 |
---|---|
visible | 默認值。內容不會被修剪,會呈現在元素框之外 |
hidden | 內容會被修剪,并且其余內容是不可見的 |
scroll | 內容會被修剪,但是瀏覽器會顯示滾動條以便查看其它的內容 |
auto | 如果內容被修剪,則瀏覽器會顯示滾動條以便查看其余的內容 |
inherit | 規(guī)定應該從父元素繼承 overflow 屬性的值 |
首先,先來看看滿足 BFC 的條件:
- float 的值不是 none
- position 的值不是 static 或者 relative
- display 的值是 inline-block、table-cell、flex、table-caption、inline-flex
- overflow 的值不是 visible
所以,只要 overflow 的值不是 visible ,都能形成 BFC。
這樣,就可以讓容器內的元素不受外面影響。
BFC是一個名詞,是一個獨立的布局環(huán)境,我們可以理解為一個箱子(實際上是看不見摸不著的),箱子里面物品的擺放是不受外界的影響的。轉換為BFC的理解則是:BFC中的元素的布局是不受外界的影響(我們往往利用這個特性來消除浮動元素對其非浮動的兄弟元素和其子元素帶來的影響。)
拓展閱讀:
4. BFC
是什么?如何形成 BFC
,有什么作用?
Block formatting contexts,塊級格式化上下文。
創(chuàng)建了 BFC 的元素就是 1 個獨立的盒子,不過只有 Block-level box 可以參與創(chuàng)建 BFC,它規(guī)定了內部的 Block-level box 如何布局,并且與這個獨立盒子里的布局不受外部影響,當然它也不會影響到外面的元素。
BFC 是個很奇怪的東西,它一直隱式地存在CSS的樣式里,但是要記住 BFC 是頁面元素里一個獨立存在作用塊,它不影響它外面的布局,外面的元素也不會影響到 BFC 里面的布局。
定義:浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如:inline-blocks, table-cells, table-captions),以及 overflow 值不是 “visible” 的塊級盒子,都會為他們的內容創(chuàng)建新的 BFC (塊級格式上下文)。
一個 HTML 元素要創(chuàng)建 BFC ,則滿足下列的任意一個或多個條件即可:
- float 的值不是 none
- position 的值不是 static 或者 relative
- display 的值是 inline-block、table-cell、flex、table-caption、inline-flex
- overflow 的值不是 visible
作用:
- 撐開父元素
- 阻止外邊距
- 清除浮動的文字環(huán)繞和位置的影響
BFC 是一個獨立的布局環(huán)境,其中的元素布局是不受外界的影響,并且在一個 BFC 中,塊盒與行盒(行盒由一行中所有的內聯元素所組成)都會垂直地沿著其父元素的邊框排列。
BFC 有以下特性:
- 內部的 Box 會在垂直方向,從頂部開始一個接一個地放置。
- Box 垂直方向的距離由 margin 決定。屬于同一個 BFC 的 2 個相鄰 Box 的 margin 會發(fā)生疊加。
- 每個元素的 margin box 的左邊,與包含塊 border box 的左邊相接觸(對于從左到右的格式化,否則相反)。即使存在浮動也是如此。
- BFC 的區(qū)域不會與 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>
清理浮動的方法
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>
父容器添加一個看不見的塊元素( :after )來清理浮動。
需要注意的是,為了兼容 IE6 和 IE7,要添加一條 zoom:1; 來觸發(fā) 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>
雖然很多地方以“將來瀏覽器可能不兼容”為由,不建議使用這個方法。但是短時間內瀏覽器不會在這個問題上后退處理。另外,這個方法無需添加額外的 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>
給浮動元素的容器添加浮動屬性也可清除內部浮動。但是這會對接下來的文檔造成影響。
建議,在容器原本就浮動,或者容器使用了絕對定位時使用這個方法。不要在主要布局中使用。
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 屬性。
要確保后面的元素與浮動元素同在一個容器(.container)內。
如果 .content 在 .container 后面,建議使用 :after 偽元素清理。
總結:
在網頁主要布局中,使用 :after 偽元素作為主要清理浮動方式。
在小模塊( ul )使用 overflow: hidden; (留意可能產生的隱藏溢出元素問題。
如果本身就是浮動元素則可自動清除內部浮動,無需額外處理。
正文中,使用鄰接元素清理之前的浮動。
需要熟悉各種清理方式的原理和利弊。
拓展閱讀:
6. 以下代碼每一行的作用是什么?為什么會產生作用?和 BFC 撐開空間有什么區(qū)別?
.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; 縮放頁面,重新排版,父元素重新計算浮動元素的高度。父容器就因此撐開了。