相信全部前端開發者的入門課,都是從div和css開始的,CSS做爲基礎中的基礎,除了讓頁面由於樣式而變得豐富美觀外,更是決定了頁面元素的排列布局,然而不少時候,當咱們對CSS只知其一;不知其二,咱們總會在開發中遇到元素不能按照咱們所想的那樣呈現出來的問題,因此本文就來系統的講講CSS的佈局定位。css
首先,咱們來了解構成頁面的元素。在CSS中,咱們的每一個元素本質上都是一個盒子,盒模型決定了一個元素的大小和他所佔大小,盒模型由如下幾部分組成:html
那麼元素的大小到底取決於什麼呢?目前有兩種盒模型:W3C盒模型
和IE盒模型
,兩種盒模型的計算方法不一樣,在CSS中,咱們能夠用box-sizing
指定使用哪一種方式計算:前端
看個例子:css3
// W3C盒模型
<style>
.box {
width: 200px;
height: 200px;
padding: 10px;
margin: 10px;
border: 5px solid red;
background-color: yellowgreen;
}
</style>
<div class="box"></div>
複製代碼
效果:chrome
// IE盒模型
<style>
.box {
width: 200px;
height: 200px;
padding: 10px;
margin: 10px;
border: 5px solid red;
background-color: yellowgreen;
box-sizing: border-box;
}
</style>
<div class="box"></div>
複製代碼
效果:瀏覽器
display
屬性display
用於定義創建佈局時元素生成的顯示框類型,會影響到兄弟元素之間的佈局,他的取值有如下幾種:bash
下面咱們將對inline-block
,flex
,run-in
這幾個屬性作詳細講解。佈局
inline-block
和float
,flex
並稱實現元素行內顯示的「三巨頭」,相比較flex的豐富屬性,inline-block就略顯樸素,使用也十分簡單,看起來彷佛徹底不值得對它進行詳細介紹,但不知道大家在使用的時候是否也踩過那些inline-block的坑,因此這裏咱們來說講inline-block的必坑指南post
咱們先來看一個例子:學習
<div class="content">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
.content {
background-color: yellow;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
width: 100px;
height: 50px;
background-color: red;
}
複製代碼
實現的效果:
font-size:0
。
<div class="content">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
.content {
background-color: yellow;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
width: 100px;
height: 50px;
background-color: red;
}
複製代碼
效果:
這個問題,是在開發的時候偶然碰見的,話很少說,先看看這兩個例子:
<div class="content">
<div class="cell">有內容</div>
<div class="cell"></div>
<div class="cell">有內容</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
width: 100px;
height: 50px;
font-size: 16px;
background-color: #666;
color: #fff;
}
複製代碼
效果:
<div class="content">
<div class="cell">有內容</div>
<div class="cell" id="spec">有內容</div>
<div class="cell">有內容</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
box-sizing: border-box;
width: 100px;
height: 50px;
line-height: 50px;
border-radius: 50px;
margin: 5px;
font-size: 16px;
text-align: center;
background-color: #fff;
color: #333;
}
.active {
border: 2px solid #E20000;
color: #E20000;
}
let spec = document.getElementById("spec");
let flag = false;
spec.addEventListener("click", () => {
flag = !flag;
if (flag) {
spec.classList.add('active')
} else {
spec.classList.remove('active')
}
});
複製代碼
效果:
測量結果顯示,這三個元素的高度同樣,並無發生改變,那麼到底是什麼緣由致使了行內元素高度塌陷、上下抖動的呢?
其實形成這一結果的是vertical-align
屬性。inline-block
做爲行內塊元素,也遵循行內元素的vertical-align
垂直對齊方式,vertical-align
的取值有如下幾種:
<length>
:將元素的基線對準給定長度高於其父元素的基線。<percentage>
:像<長度>值,百分比是line-height屬性的百分比。在默認狀況下,會根據baseline
進行定位,文字的定位不一樣,最終致使了整個塊元素的高度塌陷。想要解決這一問題,咱們只需將vertical-align
設置爲top
,以下: 狀況一:
<div class="content">
<div class="cell">有內容</div>
<div class="cell"></div>
<div class="cell">有內容</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
vertical-align: top;
width: 100px;
height: 50px;
font-size: 16px;
background-color: #666;
color: #fff;
}
複製代碼
<div class="content">
<div class="cell">有內容</div>
<div class="cell" id="spec">有內容</div>
<div class="cell">有內容</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
height: 100px;
}
.cell {
display: inline-block;
vertical-align: top;
box-sizing: border-box;
width: 100px;
height: 50px;
line-height: 50px;
border-radius: 50px;
margin: 5px;
font-size: 16px;
text-align: center;
background-color: #fff;
color: #333;
}
.active {
border: 2px solid #E20000;
color: #E20000;
}
let spec = document.getElementById("spec");
let flag = false;
spec.addEventListener("click", () => {
flag = !flag;
if (flag) {
spec.classList.add('active')
} else {
spec.classList.remove('active')
}
});
複製代碼
run-in
這個屬性值是在css3中被引入的,官方對他的描述是:
此元素會根據上下文做爲塊級元素或內聯元素顯示。
這個說法讓人會有些摸不着頭腦,因此咱們直接來看個例子。
在設計文章樣式的時候,也許你遇到過須要在一行內顯示一個標題和一段內容的場景,若是使用h
標籤和p
標籤咱們可能獲得的是下面這種結果:
<div class="article">
<h1>One Point.</h1><p>Here is the description.If a run-in element precedes a block level element, the run in element will behave structurally as if it has become the block level elements first inline child element.</p>
</div>
複製代碼
h
標籤的display屬性變成
run-in
時,結果就變成了這樣。
h1 {
display: run-in;
}
<div class="article">
<h1>One Point.</h1><p>Here is the description.If a run-in element precedes a block level element, the run in element will behave structurally as if it has become the block level elements first inline child element.</p>
</div>
複製代碼
h1 {
float: left;
}
<div class="article">
<h1>One Point.</h1><p>Here is the description.If a run-in element precedes a block level element, the run in element will behave structurally as if it has become the block level elements first inline child element.</p>
</div>
複製代碼
h1 {
display: inline-block;
}
<div class="article">
<h1>One Point.</h1><p>Here is the description.If a run-in element precedes a block level element, the run in element will behave structurally as if it has become the block level elements first inline child element.</p>
</div>
複製代碼
run-in
究竟作了什麼:
block
時,該元素將表現爲inline-block
inline-block
時,該元素將表現爲block
雖然這個屬性看起來十分便利,可是這個屬性已經被大多數瀏覽器捨棄了,這也是爲何咱們平時聽到的不是特別多的緣由,瀏覽器認爲run-in破壞了HTML的表現,這些樣式上的實現,應該經過CSS去調節。 因此對於這個屬性,你們作個瞭解就能夠啦。
Flex box
多是目前用來作自適應用的最多的佈局方式了,Flex使用的豐富,也爲開發者提供了更便捷更可靠的佈局。
決定主軸的方向(即項目的排列方向)。取值:
決定了子元素如何換行。取值:
是flex-direction屬性和flex-wrap屬性的簡寫形式,默認值爲row nowrap。
決定了項目在主軸上的對齊方式。取值:
決定了項目在交叉軸上如何對齊。取值:
決定了多根軸線的對齊方式。若是項目只有一根軸線,該屬性不起做用。取值:
決定項目的排列順序。數值越小,排列越靠前,默認爲0。
決定項目的放大比例,默認爲0,即若是存在剩餘空間,也不放大。
決定項目的縮小比例,默認爲1,即若是空間不足,該項目將縮小。
決定在分配多餘空間以前,項目佔據的主軸空間(main size)。瀏覽器根據這個屬性,計算主軸是否有多餘空間。它的默認值爲auto,即項目的原本大小。
是flex-grow, flex-shrink 和 flex-basis的簡寫,默認值爲0 1 auto。後兩個屬性可選。
容許單個項目有與其餘項目不同的對齊方式,可覆蓋align-items屬性。默認值爲auto,表示繼承父元素的align-items屬性,若是沒有父元素,則等同於stretch。
在Flex box被普遍使用之前,咱們常常會利用float來實現塊元素行內兩端顯示,它的使用也十分簡單,float屬性有如下幾種取值:
float自己沒有什麼難度,可是設置了float會致使父元素的沒法被撐開,margin失效,因此清除float也就成了開發必備知識。
原始效果:
<div class="content">
<div class="cell spe1">塊1</div>
<div class="cell spe2">塊2</div>
</div>
.content {
background-color: #eee;
font-size: 0;
width: 350px;
}
.cell {
font-size: 16px;
background-color: #666;
color: #fff;
}
.spe1 {
width: 80px;
height: 20px;
float: left;
}
.spe2 {
width: 80px;
height: 30px;
float: right;
}
複製代碼
<div class="content">
<div class="cell spe1">塊1</div>
<div class="cell spe2">塊2</div>
<div class="clr"></div>
</div>
.clr {
clear: both;
}
複製代碼
.content:after {
content: '';
display: block;
visibility: hidden;
clear: both;
}
複製代碼
該方法也是利用clear:both來清除浮動,與方法一的區別在於,方法一添加了一個clear元素,而這一個是在元素內部增長一個相似於clear的效果,其中有幾個注意點:
.content {
overflow: hidden;
}
複製代碼
經過設置overflow達到清除浮動效果,其原理是建立了一個BFC,有關BFC的知識,咱們會在後面章節裏詳細介紹。
最終效果:
position
定位position
屬性決定了某個元素的定位方式,它的取值有如下幾種:
在這些屬性裏,其中relative
咱們稱之爲相對定位,absolute
爲絕對定位,fixed
爲固定定位,sticky
爲粘性定位,而這幾個定位又能夠區分爲Normal flow(常規流)
和Unnormal Flow(很是規流)
。
屬於常規流的取值:
常規流具有如下特性:
常規流裏的元素屬於格式上下文(formatting context),塊元素和行內元素表現不一樣會產生快格式上下文和行內格式上下文,也就是咱們常說的BFC
和IFC
。
BFC的建立方法:
BFC的本質就是建立一個隔離的空間,他的具體效果以下:
對於上述效果,除了1和3,彷佛都讓人有些摸不着頭腦,那麼就讓咱們經過幾個例子來仔細研究一下。
首先咱們來了解一下什麼是外邊距摺疊(margin collapse)。 在CSS中,兩個或多個毗鄰的普通流中的盒子(多是父子元素,也多是兄弟元素)在垂直方向上的外邊距會發生摺疊,這種造成的外邊距稱之爲外邊距摺疊。
那麼何時外邊距會發生摺疊呢?發生摺疊須要知足這幾種狀況:
下面讓咱們來看看代碼實例:
<div class="top"></div>
<div class="content">
<div class="cell"></div>
<div class="cell"></div>
</div>
<div class="foot">
<div class="cell2"></div>
<div class="spe"></div>
<div class="cell2"></div>
</div>
.top {
background-color: #60acfc;
width: 100px;
height: 50px;
}
.content {
margin-top: 10px;
background-color: #eee;
width: 350px;
margin-bottom: 10px;
}
.cell {
margin-top: 20px;
background-color: #5bc49f;
height: 20px;
margin-bottom: 30px;
}
.foot {
background-color: #60acfc;
width: 100px;
}
.spe {
margin: 20px 0 30px;
}
.cell2 {
height: 20px;
background-color: #eee;
}
複製代碼
效果:
.content
和.cell
的上邊距摺疊屬於第一條,最終.content
和.top
之間的邊距爲20px。.cell
之間的邊距摺疊屬於第二條,最終.cell
之間的邊距爲30px。.cell
和.content
的下邊距摺疊屬於第三條,最終.content
和.foot
之間的邊距爲30px。.spe
本身的上下邊距摺疊屬於第四條,最終.spe
佔據的間隔爲30px。如今咱們知道了margin collapse發生的狀況,那咱們蓋如何避免邊距摺疊呢?方法有如下幾種:
<div class="BFC">
<div class="left"></div>
<div class="right"></div>
</div>
.BFC {
background-color: #eee;
}
.left {
float: left;
background-color: #60acfc;
width: 100px;
height:50px;
opacity: 0.6;
}
.right {
width: 150px;
background-color: #5bc49f;
height:30px;
}
複製代碼
在咱們沒有建立BFC的時候,父元素的高度不包含浮動元素高度。
.BFC {
background-color: #eee;
overflow: hidden;
}
複製代碼
建立BFC後,父元素就會加上浮動元素高度,這個就是咱們在以前提到的清除浮動的方法之一。
<div class="BFC content">
<div class="left"></div>
<div class="right BFC">
<div class="cell"></div>
<div class="cell"></div>
</div>
</div>
.BFC {
overflow: hidden;
}
.content {
background-color: #eee;
}
.left {
float: left;
background-color: #60acfc;
width: 100px;
height:50px;
opacity: 0.6;
}
.right {
width: 150px;
background-color: #5bc49f;
height:30px;
}
.cell {
width: 20px;
margin: 5px;
background-color: #fff;
height:20px;
display: inline-block;
}
複製代碼
效果:
IFC由inline元素構成,它的佈局規則是這樣的:
那麼IFC通常有什麼用呢?
屬於很是規流的取值:
對於很是規流,由於他們脫離了正常的文檔流,因此他們不會對正常流的元素形成影響,不少時候咱們都會配合z-index
使用,前兩種相信你們都不陌生,因此就再也不多作介紹啦,下面咱們來說講sticky
。
粘性定位(sticky)能夠被認爲是相對定位和固定定位的混合。元素在跨越特定閾值前爲相對定位,以後爲固定定位。
<div class="content">
<h1 class="title">我是一塊內容</h1>
<div class="sticky"></div>
<div class="main"></div>
</div>
.content {
background-color: #eee;
}
.title {
color: #333;
}
.sticky {
position: sticky;
top: 0px;
background-color: #60acfc;
width: 100px;
height:50px;
}
.main {
width:150px;
height: 900px;
}
複製代碼
效果:
VFC,也就是Visual formatting context
,虛擬格式上下文,他有BFC
,IFC
,GFC
和FFC
這幾種類型,在前文中,咱們已經介紹了BFC
,IFC
,這裏再簡單介紹下GFC
和FFC
。
GFC(GridLayout Formatting Contexts),"網格佈局格式化上下文",當爲一個元素設置display值爲grid的時候,此元素將會得到一個獨立的渲染區域。
咱們能夠經過在網格容器(grid container)上定義網格定義行(grid definition rows)和網格定義列(grid definition columns)屬性各在網格項目(grid item)上定義網格行(grid row)和網格列(grid columns)爲每個網格項目(grid item)定義位置和空間。
那麼GFC有什麼用呢,和table又有什麼區別呢?首先一樣是一個二維的表格,但GridLayout會有更加豐富的屬性來控制行列,控制對齊以及更爲精細的渲染語義和控制。
FFC(Flex Formatting Contexts),"自適應格式化上下文",display值爲flex或者inline-flex的元素將會生成自適應容器(flex container)。 因此當咱們使用flex佈局的時候,咱們就建立了一個FFC。
至此,有關CSS佈局和定位的知識就結束了,文中若有解釋不到位的地方,歡迎你們評論指正。
參考連接: