學(xué)習(xí)建議
定位、浮動是 CSS 核心知識點,必須熟練掌握。
1.文檔流的概念指什么?有哪種方式可以讓元素脫離文檔流?
- 文檔流指的是瀏覽器在頁面放置HTML元素所用的的方法。
- 首先考慮塊元素,塊元素從上向下流,各個塊元素之間有一個換行,默認的,每個塊元素會占據(jù)頁面的整個寬度。
- 然后內(nèi)聯(lián)元素在塊元素內(nèi)部從左上方流向右下方。如果需要多行,瀏覽器會自動換行,在垂直方向上擴展外圍塊元素,來包含這些內(nèi)聯(lián)元素。
- 使用浮動
float
、絕對定位position:absolute
和固定定位position:fixed
可以讓元素脫離文檔流。
2.有幾種定位方式,分別是如何實現(xiàn)定位的,使用場景如何?
通過使用position屬性,可以選擇4種不同類型的定位,其值如下(來源自W3C):
值 | 描述 |
---|---|
inherit | 規(guī)定應(yīng)該從父元素繼承 position 屬性的值。 |
static | 默認值。沒有定位,元素出現(xiàn)在正常的流中(忽略 top, bottom, left, right 或者 z-index 聲明)。 |
relative | 生成相對定位的元素,相對于其正常位置進行定位。因此,"left:20" 會向元素的 LEFT 位置添加 20 像素。 |
absolute | 生成絕對定位的元素,相對于 static 定位以外的第一個父元素進行定位。元素的位置通過 "left", "top", "right" 以及 "bottom" 屬性進行規(guī)定。 |
fixed | 生成絕對定位的元素,相對于瀏覽器窗口進行定位。元素的位置通過 "left", "top", "right" 以及 "bottom" 屬性進行規(guī)定。 |
通過W3C的描述大致了解了position屬性各個值的含義,接下來通過一個個的demo我們來分析各個值。
- static
默認值static,沒有定位。我們寫一個例子來看看,接下里的demo都會以這個例子為參考。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>demo1</title>
<style type="text/css">
.ct{
width: 300px;
border: 1px solid black;
}
.ct p{
background: #EEEEEE;
}
</style>
</head>
<body>
<div class="ct">
<p>1.饑人谷·最有愛的前端社區(qū)</p>
<p>2.這里的教學(xué)最人性</p>
<p>3.這里的導(dǎo)師幫幫噠</p>
<p>4.這里的服務(wù)最周到</p>
<p>5.這里的課程最實用</p>
</div>
</body>
</html>
這就是position屬性默認狀態(tài)下的頁面,文檔流里的元素都處在正常的位置。
- relative:
相對定位relative,我們拿上一個默認static頁面列子作為參考:
static
我們給第二個<p>
加上position:relative并設(shè)置left和top值,看看有什么變化:
.ct p:nth-child(2){
position: relative;
top: 20px;
left: 20px;
}
從上圖我們看到:
1.第二個p元素的位置發(fā)生了變化,相對它自身向下和向右移動了20px;
2.第二個p元素擋住了與它有重疊部分其他元素的內(nèi)容。
3.其他元素的位置沒有發(fā)生變化。
所以使用相對定位時,如果設(shè)置了移動屬性,那么會導(dǎo)致元素相對自身位置發(fā)生變化,而覆蓋掉其他的元素框。但是在文檔流中,它仍然占據(jù)著原來的位置,所以其他元素的位置不會發(fā)生變化。
除外,使用相對定位的另外一個重要的作用就是產(chǎn)生一個新的定位上下文(在CSS規(guī)范中叫做包含塊),那么什么是定位上下文呢,在本文的第三個回答中有詳細解釋。
- absolute
絕對定位absolute,我們還是用默認static頁面的列子作為參考
static
我們對第三個<p>
使用position:absolute,并且為了弄清楚absolute定位的參考對象,我們對<p>
的父元素<div>
做不同的設(shè)置;
div不設(shè)置定位元素:
.ct{
width: 300px;
border: 1px solid black;
}
.ct p{
background: #EEEEEE;
}
.ct P:nth-child(3){
position: absolute;
right: 20px;
background: red;
}
div設(shè)置定位元素:
.ct{
position: relative;
/*position: absolute;*/
/*position: fixed;*/
width: 300px;
border: 1px solid black;
}
.ct p{
background: #EEEEEE;
}
.ct P:nth-child(3){
position: absolute;
right: 20px;
background: red;
}
無論div設(shè)置成absolute、relative和fixed的哪一種,其結(jié)果都一樣:
從上面的圖來看:
1.第三個p元素脫離了文檔流,其他的幾個p元素忽略了第三個p元素,重新排列了,且父元素的高度縮小,。
2.通過背景色我們看到,第三個p元素的寬度收縮了,與其內(nèi)容文字的寬度相等。
3.第三個P元素遮擋住了與它有重疊部分元素的內(nèi)容。
4.第三個P元素的位置發(fā)生了變化,在div沒有設(shè)置定位元素時,它跳出了div相對于整個頁面定位,而div設(shè)置了定位元素時,它相對于div定位。
總結(jié)一下就是生成絕對定位的元素,相對于 static 定位以外的第一個父元素進行定位(也可以說是根據(jù)最近的定位上下文來定位)。元素會具有收縮性,如果沒有設(shè)置寬度,元素會根據(jù)內(nèi)容自動調(diào)整寬度(也就是說absolute具有自適應(yīng)寬度的特性,在下面的float屬性會提到)。元素的位置通過 "left", "top", "right" 以及 "bottom" 屬性進行規(guī)定。絕對定位使元素脫離文檔流,因此不占據(jù)空間。
-
fixed
最后還是用默認static的列子做對比,
static
我們給第四個p元素設(shè)置position:fixed看看:
.ct{
position: relative;
/*position: absolute;*/
/*position: fixed;*/
width: 300px;
border: 1px solid black;
}
.ct p{
background: #EEEEEE;
}
.ct P:nth-child(4){
position: fixed;
top: 200px;
left: 20px;
background: red;
}
fixed其實特性跟absolute都一樣,唯一的區(qū)別在于定位不一樣,fixed永遠是根據(jù)瀏覽器窗口來定位,無論其他元素怎么設(shè)置,都影響不了它。
3.absolute, relative, fixed偏移的參考點分別是什么?
absolute, relative, fixed偏移的參考點實際就是他們的定義上下文。
定義上下文,CSS規(guī)范叫它“包含塊”,所以我們先學(xué)習(xí)一下定位元素包含塊(參考CSS權(quán)威指南):
- "根元素"的包含塊(也稱為初始包含塊)由用戶代理建立。在HTML中,根元素就是HTML元素,不過有些瀏覽器會使用body元素,不過有些瀏覽器會使用body作為根元素,在大多瀏覽器中,初始包含塊是一個視窗大小的矩形。
- 對于一個非根元素,如果其position值是relative或static,包含塊則由最近的快級框、表單元素或行內(nèi)組先框的內(nèi)容邊界構(gòu)成。
- 對于一個非根元素,如果其position值是absolute,包含塊設(shè)置為最近的position值不是static的祖先元素(可以是任何類型)。這個過程如下:
- 如果這幾個祖先是塊級元素,包含塊則設(shè)置為該元素的內(nèi)邊距邊界,換句話說,就是由邊框界定的區(qū)域。
- 如果這個祖先是行內(nèi)元素,包含塊則設(shè)置為該祖先元素的內(nèi)容邊界。在從左向右讀的語言中,包含塊的上邊界和左邊界是該祖先元素中的第一個框內(nèi)容區(qū)的上邊界和左邊界,包含塊的下邊界和右邊界是最后一個框內(nèi)容區(qū)的下邊界和右邊界。在從右向左度的語言中,包含塊的右邊界對應(yīng)于第一個框的右內(nèi)容邊界,包含塊的左邊界則取自最后一個框的左內(nèi)容邊界。上下邊界也是一樣。
- 如果沒有祖先,元素的包含塊定義為初始包含塊。
好吧,這段理論知識是長了點,但解釋的很清楚了。但是光是看文字迷迷糊糊的,來點圖文更容易記憶。
- absolute的定位
瀏覽器會遞歸查找該元素的所有父元素,如果找到一個設(shè)置了position:relative/absolute/fixed的元素,就以該元素為基準定位,如果沒找到,就以瀏覽器邊界定位。
上圖中的“某一層祖先元素”就是該absolute元素的定位上下文了。
這也就是為什么我們說relative的一個重要功能就是重新定義定位上下文,所以一般情況下,我們會將relative與absolute配套使用,方便我們對absolute元素定位。
- relative的定位
relative元素的定位永遠是相對于元素自身位置的,和其他元素沒關(guān)系,也不會影響其他元素。
- fixed的定位
fixed元素的定位永遠是相對于瀏覽器邊界的,和其他元素沒有關(guān)系。
z-index 有什么作用? 如何使用?
z-index屬性設(shè)置一個定位元素沿Z軸的位置,Z軸定義為垂直延伸到顯示區(qū)的軸。如果為正數(shù),則離用戶更近,為負數(shù)則表示離用戶更遠。
Z-index僅能在定位元素上奏效
通過demo來看看如果使用:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
width: 100px;
height: 100px;
background: pink;
position: absolute;
z-index: -1;
}
</style>
</head>
<body>
<div></div>
<p>1.饑人谷·最有愛的前端社區(qū)</p>
<p>2.這里的教學(xué)最人性</p>
<p>3.這里的導(dǎo)師幫幫噠</p>
<p>4.這里的服務(wù)最周到</p>
<p>5.這里的課程最實用</p>
</body>
</html>
從上圖可以看出,當(dāng)div設(shè)置了定位元素absolute并且z-index為負一時,此時文字在div區(qū)域的上面。
我們將z-index改為1看看效果:
div{
width: 100px;
height: 100px;
background: pink;
position: absolute;
z-index: 1;
}
上圖我們可以看出,此時div區(qū)域已經(jīng)在文字上面了。
還有一種情況,如果z-index的值相同怎么辦?看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
width: 100px;
height: 100px;
background: pink;
position: absolute;
z-index: 1;
}
p{
position: absolute;
z-index: 1;
}
</style>
</head>
<body>
<div></div>
<p>饑人谷·最有愛的前端社區(qū)</p>
</body>
</html>
上圖看出,p和div的z-index值都是1,但是文字還是div區(qū)域的上方。
所以,如果2個元素的z-index的值相同,那么后面的元素會懸浮在前面的元素上面。
5.position:relative和負margin都可以使元素位置發(fā)生偏移?二者有什么區(qū)別?
- position:relative可以使元素發(fā)生偏移,但是在文檔流中,它仍然占據(jù)著原來的位置,所以其他元素的位置不會發(fā)生變化。
- 負margin:通過負margin進行偏移的元素,它會放棄偏移前占據(jù)的空間,這樣它后面文檔流中的其它元素就會“流”過來填充這部分空間,所以其他元素的位置發(fā)生了變化。
看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
.ct{
width: 400px;
height: 400px;
border: 1px solid black;
margin-left: 100px;
}
.box{
width: 100px;
height: 100px;
}
.box:nth-child(1) {
background: pink;
}
.box:nth-child(2) {
background: green;
position: relative;
left: -50px;
top: -50px;
}
.box:nth-child(3) {
background: yellow;
}
</style>
</head>
<body>
<div class="ct">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
</body>
</html>
看上圖,我們對第二個box使用relative,使它向左上移動了50px,但是另外2個box的位置沒有發(fā)生改變。
那么我們對第二個box改為使用負margin呢,看看效果:
.box:nth-child(2) {
background: green;
margin-left: -50px;
margin-top: -50px;
}
可以很明顯的看到,除了第二個box自身移動意外,第三個box跟著向上移動了50px。
所以,使用負margin會改變其他元素的位置,而relative不會。
6.如何讓一個固定寬高的元素在頁面上垂直水平居中?
使用絕對定位position:absolute和負margin可以做到。
看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.ct{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #EEEEEE;
}
.box{
width: 100px;
height: 100px;
background: white;
position: absolute;
top: 50%;
left: 50%;
margin-left: -50px;
margin-top: -50px;
}
</style>
</head>
<body>
<div class="ct">
<div class="box"></div>
</div>
</body>
</html>
分析上面代碼:
先使用position:absolute,設(shè)置left和top為50%,讓box的左上角原點位于頁面的中心,再使用負margin使box向左上移動它寬高的一半,這樣就能使box在頁面中垂直居中了。
7.浮動元素有什么特征?對其他浮動元素、普通元素、文字分別有什么影響?
浮動,float,看了一些資料后發(fā)現(xiàn)浮動其實是一個非常能體現(xiàn)出人們對于CSS屬性靈活利用和深度開發(fā)的特性了。
float被設(shè)計出來的初衷是用于文字環(huán)繞效果,即對一個圖片使用float之后,它周圍的文字會環(huán)繞著它,就像這樣:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
img{
float: left;
}
</style>
</head>
<body>
<div>
<p>

1.饑人谷·最有愛的前端社區(qū)2. 這里的教學(xué)最人性 3.這里的導(dǎo)師幫幫噠 4.這里的服務(wù)最周到 5.這里的課程最實用
</p>
</div>
</body>
</html>
后來網(wǎng)頁慢慢的發(fā)展,我們需要使用排版和布局,而使用table布局將導(dǎo)致代碼量大、混亂、不利于SEO,后來發(fā)現(xiàn)使用float+div是一種不錯的排版解決方法。
所以現(xiàn)在絕大多數(shù)情況下使用float就是為了橫向排版或者多列布局了。
float的用處說完了,就要說一下它的特性了:
- float具有破壞性;
先看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
}
</style>
</head>
<body>
<div>

</div>
</body>
</html>
這里一個img包裹在一個父元素div里面,我們對img使用float看看效果:
img{
float: left;
}
從上圖我們可以看到,作為父元素的div高度無法被撐開。
這就是float的破壞性,它會破壞父元素的原本結(jié)構(gòu),使得父元素的高度發(fā)生坍塌,而造成這一現(xiàn)象的根本原因是:float會使元素脫離文檔流。
- float具有自適應(yīng)性;
還是看一個demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
}
</style>
</head>
<body>
<div>
饑人谷·最有愛的前端社區(qū)
</div>
</body>
</html>
我們給這個div使用float試試:
div{
border: 1px solid black;
float: left;
}
如圖,在使用float之后,這個div的寬度發(fā)生了變化,不再是默認的整個頁面寬度,而是把內(nèi)容的這些文字包裹了,這就是float的自適應(yīng)性(absolute也有這種特性),塊級元素設(shè)置了float之后,如果不手動設(shè)置寬度,其寬度會根據(jù)內(nèi)容自動調(diào)整。
- float可以清除縫隙
按照慣例,看demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
padding: 5px;
}
img{
border: 1px solid red;
}
</style>
</head>
<body>
<div>
[站外圖片上傳中……(3)]
[站外圖片上傳中……(4)]
[站外圖片上傳中……(5)]
</div>
</body>
</html>
上圖可以看到3張圖片之間是有縫隙的,我們給他們設(shè)置float看看:
img{
border: 1px solid red;
float: left;
}
上圖可以看到img增加了float屬性后,互相之間沒有了縫隙,緊緊的貼合了一起。
所以這也是為什么float屬性適合用于排版,就是這種特性使得各元素嚴絲合縫,就好像砌磚頭一樣。
在這里,我們需要注意的是,使用float之后的元素會變?yōu)閴K元素,對上圖中的img審查元素看看:
確實,img的display顯示的block。
在這里只列舉了一些float布局上的特性,其實關(guān)于float的特性其實還有很多,有一些很好的博客可以參考:
float是如何工作的
float深入剖析
根據(jù)上面的列子回答另外一個問題;
一個元素設(shè)置了浮動,同級的浮動元素會跟隨著一起浮動,直到遇到其他浮動元素的邊框,就像砌磚頭一樣。
由于浮動元素會脫離文檔流,其他的普通元素會忽視浮動元素,后面的元素會占據(jù)浮動元素的文檔流空間。
雖然浮動元素會脫離文檔流,但是文字是始終能察覺浮動元素的存在, 會圍繞著浮動元素,這也是設(shè)計浮動元素的初衷。
8.清除浮動指什么? 如何清除浮動?
上一個問答提到,float是具有破壞性的,它會導(dǎo)致父元素的高度發(fā)生坍塌,影響其他元素的位置,所以為了避免這種影響, 我們需要使用清除浮動。
清除浮動有下面幾個方法:
1.浮動父元素:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
padding: 5px;
float: left;
}
img{
border: 1px solid red;
float: left;
}
</style>
</head>
<body>
<div>
[站外圖片上傳中……(6)]
[站外圖片上傳中……(7)]
[站外圖片上傳中……(8)]
</div>
</body>
</html>
讓父元素也浮動并不是一個很好的方法,可能會造成新的麻煩,要謹慎使用。
2.為父元素添加overflow
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
border: 1px solid black;
padding: 5px;
overflow: auto;
/*overflow: overlay;*/
/*overflow: hidden;*/
/*overflow: scroll;*/
}
img{
border: 1px solid red;
float: left;
}
</style>
</head>
<body>
<div>
[站外圖片上傳中……(9)]
[站外圖片上傳中……(10)]
[站外圖片上傳中……(11)]
</div>
</body>
</html>
使用overflow屬性來清除浮動有一點需要注意,不能使用visible值,其他的屬性值都行。
3.clear:both
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
.ct{
border: 1px solid black;
padding: 5px;
}
img{
border: 1px solid red;
float: left;
}
.clear{
clear: both;
}
</style>
</head>
<body>
<div class="ct">
[站外圖片上傳中……(12)]
[站外圖片上傳中……(13)]
[站外圖片上傳中……(14)]
<div class="clear"></div>
</div>
</body>
</html>
在需要使用清除浮動元素的下面添加一個div元素并且定義它的樣式為“clear:both”,這種方法會增加額外的div標簽,可能會造成一些影響。
4.clearfix
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
.clearfix{
border: 1px solid black;
padding: 5px;
}
img{
border: 1px solid red;
float: left;
}
.clearfix:after{
content:"";
display: block;
clear: both;
}
.clearfix{
*zoom:1;/*兼容ie低版本*/
}
</style>
</head>
<body>
<div class="clearfix">
[站外圖片上傳中……(15)]
[站外圖片上傳中……(16)]
[站外圖片上傳中……(17)]
</div>
</body>
</html>
這種方法是目前最受推薦的,使用偽元素在元素后面創(chuàng)建一個元素塊,然后利用clear:both來清除浮動。
本文版權(quán)歸本人和饑人谷所有,轉(zhuǎn)載請注明來源。