【Web前端HTML5&CSS3】11-定位的簡介
定位的簡介
需求分析
按照我們之前所學知識,可以怎麼實現呢?
應該來說不難,很容易實現
CSS.box2 {
width: 200px;
height: 200px;
background-color: yellow;
/* 左外邊距、上外邊距 */
margin-left: 200px;
margin-top: -200px;
}
.box3 {
width: 200px;
height: 200px;
background-color: orange;
/* 上外邊距 */
margin-top: 200px;
}
我們分別給 box2 和 box3 添加了外邊距之後,就可以達到需求效果
當然也可以使用浮動來解決上述問題,但稍微麻煩一點
不管怎樣,問題也是顯而易見。我們實際開發中,頁面上的元素可能很多,這樣改必然是 牽一髮而動全身
那麼僅僅靠我們之前學習的佈局知識,不足以輕鬆應對這種場景
那麼就勢必需要一個方便我們處理這種場景的辦法,它就是定位
定位(position)
定位是一種更加高階的佈局手段
通過定位可以將元素擺放到頁面的任意位置
使用position
屬性來設定定位
可選值 | 含義 |
---|---|
static |
不開啟定位,元素是靜止的,預設值 |
relative |
開啟元素的相對定位 |
absolute |
開啟元素的絕對定位 |
fixed |
開啟元素的固定定位 |
sticky |
開啟元素的粘滯定位 |
1. 相對定位
當元素的 position 屬性值設定為relative
時,則開啟了元素的相對定位
偏移量(offset)
當元素開啟相對定位以後,可以通過偏移量來設定元素的位置
offset 屬性 | 含義 |
---|---|
top |
定位元素和定位位置的上邊距離 |
bottom |
定位元素和定位位置的下邊距離 |
left |
定位元素和定位位置的左側距離 |
right |
定位元素和定位位置的右側距離 |
定位元素垂直方向的位置由top
和bottom
兩個屬性控制,通常情況下只會使用其中之一
-
top
值越大,定位元素越靠下 -
bottom
值越大,定位元素靠上
定位元素水平方向的位置由left
right
兩個屬性控制,通常情況下只會使用其中之一
-
left
越大,定位元素越靠右 -
right
越大,定位元素越靠左
.box2 {
width: 200px;
height: 200px;
background-color: yellow;
/* 開啟相對定位 */
position: relative;
top: -200px;
left: 200px;
}
我們給 box2 設定相對定位,就得到了我們想要的頁面效果
可以看出,使用了相對定位後,只會移動自身的佈局位置,而不會對已存在的其他元素產生任何影響
相對定位的特點
-
當元素開啟相對定位以後,如果不設定偏移量元素,則元素不會發生任何變化(這裡注意,不僅僅是位置)
-
相對定位是參照於元素在文件流中的位置進行定位的(可以理解為相對於自身原始位置)
-
相對定位會提升元素的層級(表現為可以覆蓋其他元素)
-
相對定位不會改變元素的性質:塊還是塊,行內還是行內
Q1:如果給上述三個 div 都設定相對定位,那麼它們的層級關係會是什麼樣的呢?或者說誰會被誰覆蓋呢?
可以看到覆蓋關係是:box3 >> box2 >> box1
我們再稍微調整下 box3 和 box2 的前後位置
會發現覆蓋關係變成了:box2 >> box3 >> box1
可以大概猜測:在頁面文件流中,越靠下的元素開啟相對定位後,其層級越高 (這裡也只是我個人的揣測,待後續學習中驗證)(在後續學習中已得到驗證:沒有設定層級或層級z-index
設定相同值時,優先顯示靠下的元素)
Q2:相對定位的第三個特點相對定位會提升元素的層級
,是不是就類似於浮動一樣脫離了文件流?
A:我們可以對比下,浮動和相對定位的區別
- 參考系不同:浮動的參考系是其父元素;相對定位是相對於自身
- 可移動方向不同:浮動只能左右移動;相對定位是上下左右移動
- 影響不同:浮動會影響頁面佈局(包括下方元素位置影響和高度塌陷問題);相對定位不對影響頁面佈局
- 性質不同:浮動會改變元素的性質(不再獨佔一行,其寬高都會被內容撐開);相對定位不會改變元素的性質
- 文字環繞:浮動不會覆蓋文字;相對定位可以覆蓋文字(這個可以自行驗證,不再贅述)
當然,浮動和相對定位也有其相似之處
- 浮動和相對定位都是移動位置(貌似是廢話)
- 浮動和相對定位不會從父元素中移出
可以看出,浮動和相對定位的區別是更多的
最後回答一點:浮動脫離了文件流,不再佔據頁面位置;相對定位仍然佔據頁面位置(所以怎麼能夠叫 脫離文件流
呢?)
Q3:相對定位的第四個特點相對定位不會改變元素的性質:塊還是塊,行內還是行內
,但是上述例子中元素開啟相對定位後好像就不再獨佔一行了,這個怎麼理解?
A:相比於浮動元素的特點,相對定位不會改變元素的性質其實是一個相對不容易理解的問題。但其實也不難,可以把相對定位認為是元素的靈魂出竅
。其位置發生改變以後,佈局並沒有產生影響,因為它的肉體
(結構)仍然佔據著原來的那個位置。只是其靈魂
(內容)發生了移動。
Q4:相對定位的第四個特點中塊還是塊,行內還是行內
,意味著行內元素也可以使用相對定位是嗎?
A:眼見為實,耳聽為虛
,直接看示例效果
2. 絕對定位
當元素的position
屬性值設定為absolute
時,則開啟了元素的絕對定位
絕對定位的特點
- 開啟絕對定位後,如果不設定偏移量,元素的位置不會發生變化
- 開啟絕對定位後,元素會從文件流中脫離
- 絕對定位會改變元素的性質:行內變成塊,塊的寬高被內容撐開(與相對定位相反)
- 絕對定位會使元素提升一個層級
- 絕對定位元素是相對於其包含塊進行定位的(與相對定位不同)
包含塊(containing block)
正常情況下:
- 包含塊就是離當前元素最近的開啟了定位的祖先塊元素
- 如果所有的祖先元素都沒有開啟定位,則
html(根元素、初始包含塊)
就是它的包含塊
<body>
<!-- 如果box1開啟定位,則box2的包含塊是box1,否則就是body -->
<div class="box1">
<div class="box2"></div>
</div>
<!-- 如果box3開啟定位,則em的包含塊是box3,否則就是body -->
<div class="box3">
<span>
<em>hello</em>
</span>
</div>
</body>
示例
HTML<div class="box2">
2
<div class="box3">
3
<div class="box4">4</div>
</div>
</div>
- 不給 box2、box3 開起定位,box4 的包含塊是
html
- 只給 box3 開啟定位之後,box4 的包含塊是 box3
- 只給 box2 開啟定位之後,box4 的包含塊是 box2
- 給 box2、box3 都開起定位之後,box4 的包含塊是 box3
注意:這裡上述的條件是開啟定位,也就是說只要position
不是static
(預設值),那麼就滿足了其成為包含塊的必要條件
上述示例中,我們給其祖先元素都設定了相對定位。其實改成其他幾種定位方式也是可行的,我們可以看下面示例
這裡就不一一舉例了,大家可以對另外幾種定位方式進行驗證
水平方向的佈局
我們之前說過,水平方向的佈局等式:
margin-left + border-left + padding-left + width + padding-right + border-right + margin-right = 其父元素的寬度
當使用絕對定位時,需要新增left
和right
兩個值(此時規則和之前一樣,只是多添加了兩個值)
left + margin-left + border-left + padding-left + width + padding-right + border-right + margin-right + right = 其父元素的寬度
當發生過度約束時
- 如果 9 個值中沒有
auto
,則自動調整right
值以使等式滿足(之前 7 個值是margin-right
) - 如果 9 個值中有
auto
,則自動調整auto
的值以使等式滿足
可設定auto
的值:margin-left
/margin-right
/width
/left
/right
因為left
和right
的值預設是auto
,所以如果沒有設定left
和right
,當等式不滿足時,則會自動調整這兩個值
水平居中
HTML<style>
.box1 {
width: 500px;
height: 500px;
background-color: #bfa;
position: relative;
}
.box2 {
width: 100px;
height: 100px;
background-color: orange;
/* 左右外邊距設定為auto */
margin-left: auto;
margin-right: auto;
/* 絕對定位 */
position: absolute;
left: 0;
right: 0;
}
</style>
<div class="box1">
<div class="box2"></div>
</div>
垂直方向的佈局
垂直方向佈局的等式的也必須要滿足
top + margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom + top = 其父元素的高度
垂直居中
CSS.box2 {
width: 100px;
height: 100px;
background-color: orange;
/* 左右外邊距設定為auto */
margin-top: auto;
margin-bottom: auto;
/* 絕對定位 */
position: absolute;
top: 0;
bottom: 0;
}
水平垂直居中
目前,我們可以根據絕對定位進行元素的水平垂直雙方向居中,所以這個方法只是其中之一
CSS.box2 {
width: 100px;
height: 100px;
background-color: orange;
/* 左右外邊距設定為auto */
margin: auto;
/* 絕對定位 */
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
小結
- 水平佈局等式:
left + margin-left + border-left + padding-left + width + padding-right + border-right + margin-right + right = 其父元素的寬度
- 垂直佈局等式:
top + margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom + top = 其父元素的高度
- 上述等式的過度約束規則與《06-盒模型》中介紹的規則基本一致
- 只是在沒有
auto
時,會自動調整top
/bottom
/left
/right
3. 固定定位
將元素的position
屬性設定為fixed
,則開啟了元素的固定定位
固定定位的特點
固定定位也是一種絕對定位,所以固定定位的大部分特點都和絕對定位一樣
唯一不同的是,固定定位永遠參照於瀏覽器的視口(viewport,可視視窗)進行定位,不會隨網頁的滾動條滾動
示例
我們再給body
設定一個較大的高度,讓瀏覽器滾動起來,看下效果
會發現,box4 並沒有因為滾動而發生未知的變化,這也驗證了上述知識,同時也應該明白了視口
的概念
我們再對比下絕對定位
相信到這裡,大家應該又進一步地理解了固定定位與絕對定位的區別
因為固定定位跟絕對定位除了具有上述差別之後,其他的特點跟絕對定位是一樣的,所以這裡便不再贅述了
4. 粘滯定位
將元素的position
屬性設定為sticky
,則開啟了元素的固定定位
這次,我們換個方式,直接來看粘滯定位的效果
大家可以看到,右側邊欄部分在一定的情況下是固定的,滾動到上方一定位置開始發生變動
- 該元素是根據文件流進行定位的,即相對於包含塊進行偏移
- 偏移量不會影響任何其他元素的位置
- 粘性元素總是“粘”到其最近的具有“滾動機制”的祖先元素(當
overflow
為hidden
、scroll
、auto
、overlay
時建立),即使該祖先不是最近的實際滾動祖先
這裡可能最後一點比較難理解,彆著急,我們接著往下看
示例
我們拿之前的w3cschool頂部導航欄
進行下魔改
/* 設定一個高度 */
body {
height: 3000px;
}
.menu {
width: 1211px;
height: 48px;
background-color: #e8e7e3;
margin: 100px auto;
/* 開啟粘滯定位 */
position: sticky;
top: 10px;
}
因為在視訊中老師並沒有對sticky
屬性做過多的介紹,只是要求我們瞭解一下,因為在實際開發中,也是結合 js 去實現的,所以我這裡同樣也就不再深入帶大家一起看了
粘滯定位的特點
- 粘滯定位和相對定位的特點基本一致(視訊中說是和相對定位一致,不過我對比了一下,很多特點是不同的,感覺倒是和固定定位更相似,這裡存疑)
- 不同的是粘滯定位可以在元素到達某個位置時將其固定
需要注意的是,sticky
屬性並不相容 IE(PS:不過微軟官方已經宣佈將在 2022 年停止對 IE 的維護,IE 將成為歷史。雖然我們經常詬病 IE,但作為當年瀏覽器的一霸,在廢棄多年後,不知道還會不會有所懷念,畢竟它代表著我們不斷逝去的青春)
5. 幾種定位的對比
我們通過上面的學習,知道position
屬性有五個可選值
但static
是預設值,即不開啟定位,所以我們只需要對比 4 種定位方式即可
定位方式 | 是否不設定偏移量,元素不會發生改變 | 是否脫離文件流 | 是否改變元素性質 | 是否提升元素層級 | 參考系 |
---|---|---|---|---|---|
relative (相對定位) |
√ | × | × | √ | 參照於元素在文件流中的位置 |
absolute (絕對定位) |
× | √ | √ | √ | 參照於其包含塊 |
fixed (固定定位) |
× | √ | √ | √ | 參照於瀏覽器的視口 |
sticky (粘滯定位) |
× | √ | √ | √ | 參照於瀏覽器的視口 |
6. 補充:元素層級
對於開啟了定位元素,可以通過z-index
屬性來指定元素的層級
-
z-index
需要一個整數作為引數,值越大元素的層級越高,元素的層級越高越優先顯示 - 如果元素的層級一樣,則優先顯示靠下的元素
- 祖先的元素的層級再高,也不會蓋住後代元素
示例
HTML<style>
div {
font-size: 40px;
}
.box1 {
width: 200px;
height: 200px;
background-color: #bfa;
position: absolute;
top: 0;
left: 0;
}
.box2 {
width: 200px;
height: 200px;
background-color: orange;
position: absolute;
top: 50px;
left: 50px;
}
.box3 {
width: 200px;
height: 200px;
background-color: salmon;
position: absolute;
top: 100px;
left: 100px;
}
.box4 {
width: 100px;
height: 100px;
background-color: skyblue;
position: absolute;
bottom: 0;
left: 0;
}
</style>
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">
3
<div class="box4">4</div>
</div>
存疑問題
Q:浮動也有層級概念嗎?如果有,浮動和定位的層級關係是什麼樣的?
A:null / none / undefined 調了一下,出現幾種現象
- 給
float
設定z-index
多大都沒用,還是會被覆蓋 - 預設情況,沒有設定
z-index
或設定z-index
大小 ≥0 時,浮動層級
沒有定位的層級高 - 設定
z-index
<0 時,浮動層級
可以定位的層級高
浮動層級
(不知道有沒有這個概念,本身就是存疑問題,現在這種情況看起來應該是沒有這個概念了)
7. 總結
一般情況下,
- 頁面的整體結構大多采用浮動、塊進行佈局
- 頁面某些模組結構一般採用定位進行微調
8. 練習:京東輪播圖
css 程式碼
CSS/* 整體居中 */
.box {
width: 590px;
height: 470px;
/* 水平垂直雙方向居中 */
margin: auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
/* ======輪播圖Start====== */
.img_list li {
/* 每個輪播圖絕對定位,讓其重疊 */
position: absolute;
}
.img_list li:nth-child(1) {
/* 目前還沒有學習js,暫時做成靜態切換層級 */
z-index: 1;
}
/* 全域性影象大小 */
.img_list img {
/* 我這裡之所以要設定寬高,是因為下載的圖片大小不全是一樣大的 */
/* 但是一般情況下,這些圖片都會裁剪成統一大小,所以可以不用設定 */
width: 590px;
height: 470px;
}
/* ======輪播圖End====== */
/* ======輪播圓Start====== */
.circle_list {
height: 20px;
/* 開啟絕對定位 */
position: absolute;
bottom: 20px;
left: 30px;
z-index: 2;
/* 參考京東原網頁,整體字型設定樣式,這種設定方式還不太懂 */
/* 其實也可以不設定,不過每個輪播圓之間的間距跟原來就不太一樣了 */
font-size: 0;
text-align: center;
}
/* 輪播圓細節 */
.circle_list .circle {
/* 這裡設定display: inline-block; 也是一樣的 */
float: left;
height: 8px;
width: 8px;
background-color: rgba(255, 255, 255, 0.4);
margin-right: 4px;
/* 畫圓,這個按照課程中的畫法,按照網頁原始碼調出來的有點問題 */
background-clip: content-box;
border: 3px transparent solid;
border-radius: 50%;
}
/* 輪播圓懸浮效果 */
.circle_list .circle:hover,
.circle_list .circle:nth-child(1) {
background-color: #fff;
border: 3px rgba(0, 0, 0, 0.1) solid;
}
/* ======輪播圓End====== */
html 程式碼
HTML<div class="box">
<ul class="img_list">
<li>
<a href="#"><img src="assets/lbt/1.jpg" alt="" /></a>
</li>
<li>
<a href="#"><img src="assets/lbt/2.jpg" alt="" /></a>
</li>
<li>
<a href="#"><img src="assets/lbt/3.jpg" alt="" /></a>
</li>
<li>
<a href="#"><img src="assets/lbt/4.jpg" alt="" /></a>
</li>
<li>
<a href="#"><img src="assets/lbt/5.jpg" alt="" /></a>
</li>
<li>
<a href="#"><img src="assets/lbt/6.jpg" alt="" /></a>
</li>
<li>
<a href="#"><img src="assets/lbt/7.jpg" alt="" /></a>
</li>
<li>
<a href="#"><img src="assets/lbt/8.jpg" alt="" /></a>
</li>
</ul>
<!-- 我這裡結構並沒有完全按照課程中的結構來,但實現效果是一樣的 -->
<ul class="circle_list">
<li class="circle"></li>
<li class="circle"></li>
<li class="circle"></li>
<li class="circle"></li>
<li class="circle"></li>
<li class="circle"></li>
<li class="circle"></li>
<li class="circle"></li>
</ul>
</div>
別忘了,引入reset
樣式
效果
等到後面學習了 js,就可以實現自動輪播了,到時候再補充完善
主要運用
- 水平垂直雙方向居中(水平垂直方向等式)
-
absolute
開啟絕對定位,使其重疊,達到隱藏效果 -
z-index
設定層級,實現圖片輪播 -
border-radius
畫圓,transparent
邊框透明,background-clip:content-box
隱藏邊框