常見定位方案
- 普通流(normal flow)
在普通流中, 元素按照其HTML中的先后位置自上而下布局做祝, 在這個過程中混槐, 行內元素水平排列, 直到行內被占滿后換行翻诉; 塊級元素則會渲染為完整的新行碰煌。除非另外指定芦圾,否則所有元素默認都是普通流定位个少, 也可以說, 普通流中元素的位置由該元素在HTML文檔中的位置決定眯杏。
- 浮動(float)
在浮動布局中夜焦,元素首先按照普通流的位置出現(xiàn), 然后根據(jù)浮動的方向盡可能的向左邊或者向右邊偏移岂贩, 其效果與印刷版中的文本環(huán)繞相似茫经。
- 絕對定位(absolute positioning)
在絕對定位布局中, 元素會整體脫離文檔流萎津, 因此絕對定位元素不會對其兄弟元素造成影響卸伞, 而元素具體的位置由絕對定位的坐標決定。
BFC
BFC即Block Formatting Contexts(塊級格式化上下文)锉屈, 它屬于上述定位方案的普通流荤傲。
具有BFC特性的元素可以看作是隔離了的獨立容器颈渊, 容器里面的元素不會在布局上影響到外面的元素查蓉, 并且BFC具有普通容器所沒有的一些特性妹田。
通俗的說驶拱, 可以把BFC理解為一個封閉的大箱子, 箱子內的元素無論怎么折騰税迷, 都不會影響到外部元素哥牍。
1.觸發(fā)BFC
只要元素滿足下面任意一條件即可觸發(fā)BFC特性:
- body 根元素
- 浮動元素: float 除 none以外的值
- 絕對定位: position(absolute/fixed)
- display除了visible以外的值(hidden、auto、scroll)
2. BFC特性及應用
- 同一個BFC下抠忘,外邊距會發(fā)生折疊
<section>
<style>
div {
width: 100px;
height: 100px;
background: #f00;
margin: 100px;
}
</style>
<body>
<div></div>
<div></div>
</body>
</section>
從效果上看囚灼, 因為兩個div元素都處于同一個BFC容器下(這里指的是body元素)所以第一個div的下邊距和第二個div的上邊距發(fā)生了重疊蝎抽, 因此兩個盒子之間距離只有100px养交,而不是200px。
這不是css的bug,我們可以理解為是一種規(guī)范, 如果想要避免外邊距重疊座每, 可以將其放在不同的BFC容器中。 如下:
<section>
<style>
.container{
overflow: hidden;
}
p {
width: 100px;
height: 100px;
background: #f00;
margin: 100px;
}
</style>
<div class="container">
<p></p>
</div>
<div class="container">
<p></p>
</div>
</section>
這個時候孵运, 兩個盒子邊距就變成了200px
-
BFC可以包含浮動的元素(清除浮動)
浮動的元素都會脫離普通文檔流:
<section>
<style>
.first {
width: 100px;
background: #f00;
float: left;
}
.second {
width: 200px;
height: 200px;
border: 1px #00f solid;
}
</style>
<div class="first">
我是第一個元素我是第一個元素我是第一個元素
</div>
<div class="second">
我是第二個元素我是第二個元素我是第二個元素我是第二個元素我是第二個元素我是第二個元素
</div>
</section>
這個時候第二個元素被第一個浮動元素所部分覆蓋,(文本信息不會被浮動元素覆蓋)如果想避免元素被覆蓋, 可觸發(fā)第一個元素的BFC特性俯萌, 在第二個元素中加入overflow: hidden; 就會變成如下效果:
這個方法可以用來實現(xiàn)兩列自適應布局
IFC
IFC棋恼, inline Formatting Contexts, 也就是 ”內聯(lián)格式化上下文“悦施。
符合以下任何一條件即會生成一個IFC
- 塊級元素中僅包含內聯(lián)級別元素
形成條件非常簡單, 需要注意的是當IFC中有塊級元素插入時, 會產生兩個匿名塊將父元素分割開來,產生兩個IFC鞋吉。
IFC布局規(guī)則:
- 子元素水平方向橫向排列赊锚,并且垂直方向起點為元素頂部友多。
- 子元素只會計算橫向樣式空間骗绕,(padding, border, margin), 垂直方向樣式空間不會被計算(padding, border, margin )。
- 在垂直方向上, 子元素會以不同形式來對齊(vertical-align)棺亭。
- 能把在一行上的框都完全包含進去的一個矩形區(qū)域岳守, 被稱為該行的行框(line box)。行框的寬度是由包含塊(containing box)和與其中的浮動來決定的。
- IFC中的”line box“一般左右邊貼緊其包含塊, 但float元素會優(yōu)先排列。
- IFC中的”line box“高度由css行高計算規(guī)則來確定, 同個IFC的多個line box高度可能會不同纪吮。
- 當line-level boxes 的總寬度少于包含它們的line box時, 其水平渲染規(guī)則由 text-align屬性值來決定榔组。
- 當一個”inline box“超過父元素的寬度時锨推, 它會被分割成多個boxes, 這些boxes分布在多個”line box“中。 如果子元素未設置強制換行的情況下慨削, ”inline box“將不可被分割, 將會溢出父元素。
相對于BFC, IFC的規(guī)則一大推, 很少會有人耐心看下去夺欲, 舉個例子大概明白其特性纸泄。
很多時候弓千,上下間距不生效可以使用IFC來解釋
<section>
<style>
.wrap {
display: inline-block;
border: 1px #f00 solid;
}
span {
margin: 20px;
background: #00f;
}
</style>
<div class="wrap">
<span>文本一</span>
<span>文本二</span>
</div>
</section>
上里可以看出鹊碍, span左右margin撐開器紧, 上下margin未撐開, 符合IFC規(guī)范:只計算橫向樣式空間士飒, 不計算縱向樣式空間。
多個元素水平居中
<section>
<style>
.wrap{
border: 1px #f00 solid;
width: 200px;
text-align: center;
}
span{
background: #00f;
}
</style>
<div class="wrap">
<span>文本一</span>
<span>文本二</span>
</div>
</section>
水平排列規(guī)則根據(jù)IFC容器的text-align值來排列,可以用來實現(xiàn)多個子元素的水平居中袱瓮。
float元素優(yōu)先排列
<section>
<style>
.wrap{
border: 1px #f00 solid;
width: 200px;
}
span{
background: #00f;
}
.fl{
float: left;
}
</style>
<div class="wrap">
<span>文本一</span>
<span>文本二</span>
<span class="fl">文本三</span>
</div>
</section>
IFC中具備float屬性值的元素優(yōu)先排列瘫里, 在很多場景中用來在文章段落開頭添加”tag“可以用到拨脉。
利用IFC還可以做很多其他的事情箕昭,例如:解決元素垂直居中积暖、多個文本元素行高不一致排列的混亂。