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

1.饑人谷·最有愛的前端社區2. 這里的教學最人性 3.這里的導師幫幫噠 4.這里的服務最周到 5.這里的課程最實用
</p>
</div>
</body>
</html>
后來網頁慢慢的發展,我們需要使用排版和布局,而使用table布局將導致代碼量大、混亂、不利于SEO,后來發現使用float+div是一種不錯的排版解決方法。
所以現在絕大多數情況下使用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的破壞性,它會破壞父元素的原本結構,使得父元素的高度發生坍塌,而造成這一現象的根本原因是: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>
我們給這個div使用float試試:
div{
border: 1px solid black;
float: left;
}
如圖,在使用float之后,這個div的寬度發生了變化,不再是默認的整個頁面寬度,而是把內容的這些文字包裹了,這就是float的自適應性(absolute也有這種特性),塊級元素設置了float之后,如果不手動設置寬度,其寬度會根據內容自動調整。
- 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張圖片之間是有縫隙的,我們給他們設置float看看:
img{
border: 1px solid red;
float: left;
}
上圖可以看到img增加了float屬性后,互相之間沒有了縫隙,緊緊的貼合了一起。
所以這也是為什么float屬性適合用于排版,就是這種特性使得各元素嚴絲合縫,就好像砌磚頭一樣。
在這里,我們需要注意的是,使用float之后的元素會變為塊元素,對上圖中的img審查元素看看:
確實,img的display顯示的block。
在這里只列舉了一些float布局上的特性,其實關于float的特性其實還有很多,有一些很好的博客可以參考:
float是如何工作的
float深入剖析
根據上面的列子回答另外一個問題;
一個元素設置了浮動,同級的浮動元素會跟隨著一起浮動,直到遇到其他浮動元素的邊框,就像砌磚頭一樣。
由于浮動元素會脫離文檔流,其他的普通元素會忽視浮動元素,后面的元素會占據浮動元素的文檔流空間。
雖然浮動元素會脫離文檔流,但是文字是始終能察覺浮動元素的存在, 會圍繞著浮動元素,這也是設計浮動元素的初衷。
8.清除浮動指什么? 如何清除浮動?
上一個問答提到,float是具有破壞性的,它會導致父元素的高度發生坍塌,影響其他元素的位置,所以為了避免這種影響, 我們需要使用清除浮動。
清除浮動有下面幾個方法:
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>
這種方法是目前最受推薦的,使用偽元素在元素后面創建一個元素塊,然后利用clear:both來清除浮動。
本文版權歸本人和饑人谷所有,轉載請注明來源。