CSS 中有時候需要一些特殊佈局,用正常流做不出來的效果。這時我們就可以使用破壞流和保護流的那些 CSS 屬性來實現這些效果。
float
float
屬性指定一個元素應沿其容器的左側或右側放置,允許文字和內聯元素環繞它。該元素從網頁的正常流(文件流)中移除,儘管仍然保持部分的流動性(與絕對定位相反)。
當一個元素浮動之後,它會被移出正常的文件流,然後向左或者向右平移,一直平移直到碰到了所處的容器的邊框,或者碰到另外一個浮動的元素。
float
最初的設計目的是為了實現文字環繞效果,主要指的就是文字環繞圖片顯示的效果。所以就導致我們用它實現一些複雜的佈局時問題一大堆。所以能不用float
佈局就不用。
float
主要有 3 個屬性值none
, left
和right
。
當一個元素浮動時它具有以下特性:
- 包裹性 - 浮動元素會包裹它的子元素(浮動元素子元素 100x100,則浮動元素也是 100x100)
- 自適應 - 如果浮動元素子元素有一堆文字時,它的最終寬度為它的父級寬度。
- 塊狀話並格式化上下文 -
float
的屬性值不為none
,則其display
計算值就是block
或者table
- 破壞文件流 - 會讓父元素的高度塌陷
- 沒有
margin
合併
float
還有一個特性是行框盒子和浮動元素的不可重疊
,正常定位狀態下只會跟隨浮動元素,而不會發生重疊。
<div>
<img src="http://">
</div>
<p>文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字</p>
<style>
div {padding-top: 10px; background: #ccc;}
img { width: 100px; float: left;}
</style>
複製程式碼
我們可以看到p
和img
重疊了,但是p
中的行框盒子則是跟隨浮動元素。
流體佈局
float
可以很方便的實現多欄佈局。
<div class='page'>
<div class="float">
<p>float</p>
</div>
<div class="a">
文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
</div>
</div>
<style>
.float { float: left; width: 60px;background: green;}
.a { margin-left: 70px; background: red; }
</style>
複製程式碼
<div>
<div class="l">left</div>
<div class="r">right</div>
<h1>title</h1>
</div>
<style>
.l { float: left; }
.r { float: right; }
h1 { margin: 0 50px; text-align: center;}
</style>
複製程式碼
清除浮動
clear
屬性是專門來處理float
帶來的高度塌陷等問題的。 它指定一個元素是否必須移動(清除浮動後)到在它之前的浮動元素下面。clear
屬性適用於浮動和非浮動元素。
它一共有 4 個值,none
,left
,right
和both
。
其中left
和right
是沒什麼作用的,因為在要使用left
和right
的情況下都可以使用both
替換。
clear
屬性是讓自身不能和前面的浮動元素相鄰,它對後面的元素是不管的,left
和right
是不能同時存在的。
clear
屬性只有塊級元素才有效的,所以我們用::after
偽類時都要將它的display
設定為block
。
.clear:after {
content: '';
display: block;
clear: both;
}
複製程式碼
clear
其實並沒有清除浮動而是讓自己不和float
元素在一行顯示。
<div class="page">
<img src="https://">
文字文字文字文字文字文字
</div>
<div>
文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字
</div>
<style>
.page:after {
content: '';
display: table;
clear: both;
}
.page img {
float:left;
width: 100px;
}
.page + div {
margin-top: -2px;
}
</style>
複製程式碼
可以看到雖然使用了clear
,但是clear
後面的元素任有可能受float
的影響。
BFC
塊格式化上下文(Block Formatting Context,BFC) 是 Web 頁面的視覺化 CSS 渲染的一部分,是塊盒子的佈局過程發生的區域,也是浮動元素與其他元素互動的區域。
BFC 就像結界,它會形成一個封閉的空間,裡面的子元素不會影響到外面的元素,所以 BFC 也可以用來清除浮動。
在以下情況下會觸發 BFC:
- 根元素或包含根元素的元素
- 浮動元素(元素的
float
不是none
) position
的值不為relative
和static
overflow
值不為visible
的塊元素display
的值為table-cell
、table-caption
和inline-block
中的任何一個- 彈性元素和網格元素
流體佈局
BFC 可以實現更健壯、更智慧的自適應佈局。
<div>
<div></div>
<p>文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字</p>
</div>
<style>
div > div {
width: 50px;
height: 50px;
float: left;
background: red;
}
p { overflow: hidden; }
</style>
複製程式碼
普通流體元素在設定了overflow:hidden
後,會自動填滿容器中除了浮
動元素以外的剩餘空間,形成自適應佈局效果。
overflow
overflow
是最適合清除浮動影響的元素,而不是clear
。但是它的本職工作還是裁剪。它是overflow-x
和overflow-y
的簡寫屬性。
overflow
裁剪是沿著border
內邊緣裁剪的。
<div>
<p>文字文字文字文字文字文字文字文字文字文字文字文字</p>
</div>
<style>
div {
border: 10px solid;
padding: 10px;
overflow: hidden;
}
p {
white-space: nowrap;
}
</style>
複製程式碼
它常用屬性有:
visible
預設值。內容不會被修剪,會呈現在元素框之外hidden
內容會被修剪,並且其餘內容不可見scroll
內容會被修剪,瀏覽器會顯示滾動條以便檢視其餘內容,滾動條區域一直在auto
由瀏覽器定奪,如果內容被修剪,就會顯示滾動條
overflow-x
和 overflow-y
overflow-x
和overflow-y
屬性中的一個值設定為visible
而另
外一個設定為scroll
、auto
或hidden
,則visible
的樣式表現會如同auto
。
也就是說永遠不可能實現一個方向溢位剪裁或滾動,另一方向內容溢位顯示的效果。
滾動條
HTML 中只有兩個標籤預設可以產生滾動條,html
和textarea
,因為它們的overflow
不是visible
。
滾動欄佔據寬度的特性最大的問題就是頁面載入的時候水平居中的佈局可能會產生晃動,因為窗體預設是沒有滾動條的,而 HTML 內容是自上而下載入的,就會發生一開始沒有 滾動條,後來突然出現滾動條的情況,此時頁面的可用寬度發生變化,水平居中重新計算,導 致頁面發生晃動。
這裡有一個防止晃動的小技巧。
html {
overflow-y: scroll; /* for IE8 */
}
:root {
overflow-y: auto;
overflow-x: hidden;
}
:root body {
position: absolute;
}
body {
width: 100vw;
overflow: hidden;
}
複製程式碼
對於支援-webkit-
字首的瀏覽器,我們可以用以下偽類自定義滾動條。
::-webkit-scrollbar
整體部分::-webkit-scrollbar-button
兩端按鈕::-webkit-scrollbar-track
外層軌道::-webkit-scrollbar-track-piece
內層軌道::-webkit-scrollbar-thumb
滾動滑塊::-webkit-scrollbar-corner
邊角
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-thumb {
background-color: rgba(0,0,0,.3);
border-radius: 10px;
}
::-webkit-scrollbar-track {
background-color: transparent;
border-radius: 10px;
}
複製程式碼
文字溢位
CSS 中有很多屬性要想生效都必須要有其他 CSS 屬性配合。比如文字溢位顯示...
。
.ell {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
/* 這 3 個宣告缺一不可 */
}
/* 多行文字省略,無需依賴 overflow */
.ell2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
複製程式碼
錨點定位
一般實現錨點定位有兩種方法,一種是使用a
的href
和name
屬性,如:
<a href="#1">Title ></a>
<a name="1">Title</a>
複製程式碼
還有一種是使用a
的href
和其他元素的id
屬性。
<a href="#1">Title ></a>
<h2 id="1">Title</h2>
複製程式碼
它的原理是當我們點選一個連結,改變了位址列的 hash 值,而且這個 hash 值可以在頁面中找到對應的元素,並且是非隱藏狀態,否則不會發生定位行為。
我們也可以使用一個簡單的#
來實現返回頂部功能,它可以將頁面是定位到頂部。
錨點定位行為的發生,本質上是通過改變容器滾動高度或者寬度來實現的。水平和垂直方向一樣,一般發生垂直滾動的多。
錨點定位也可以發生在普通的容器元素上,而且定位行為的發生是由內而外的。由內而外
指的是,普通元素和窗體同時可滾動的時候,會由內而外觸發所有可滾動窗體的錨點定位行為。
<div>
<div class="overflow">
<p>文字</p>
<p>文字</p>
<p>文字</p>
<h2 id="1">Title</h2>
</div>
<a href="#1">title ></a>
<div style="height: 500px;"></div>
</div>
<style>
.overflow {
overflow: hidden;
height: 2em;
background: #ccc;
}
</style>
複製程式碼
我們發現overflow
滾動到了h2
元素位置(雖然沒有滾動條),頁面的滾動條也滾動到了可以顯示h2
元素的位子。
用這個特點我們可以實現一個無需js
的幻燈片效果。但是當我們點選切換按鈕的時候,頁面的滾動條也會自動滾動。
這時候我們就可以使用focus錨點定位
,它是利用label
的for
屬性和input
的id
屬性。
<div>
<div><input id="one">1</div>
<div><input id="two">2</div>
<div><input id="three">3</div>
</div>
<div>
<label for="one">1</label>
<label for="two">2</label>
<label for="three">3</label>
</div>
複製程式碼
除了點選按鈕切換,我們還可以使用tab
鍵切換。
position
position
屬性用於指定一個元素在文件中的定位方式。top
,right
,bottom
和left
屬性則決定了該元素的最終位置。
position
一共有 5 個值:
static
正常的佈局行為,即元素在文件常規流中當前的佈局位置。relative
元素先放置在未新增定位時的位置,再在不改變頁面佈局的前提下調整元素位置absolute
脫離正常文件流,通過指定元素相對於最近的非static
定位祖先元素的偏移,來確定元素位置fixed
和absolute
類似,但是它是相對於螢幕視口的位置來指定元素位置。sticky
盒位置根據正常流計算,然後相對於該元素在流中的 flow root(BFC)和最近的塊級祖先元素定位。在所有情況下,該元素定位均不對後續元素造成影響。
定位元素的型別主要有:
相對定位元素
- 是計算後位置屬性為relative
的元素。絕對定位元素
- 是計算後位置屬性為absolute
或fixed
的元素。粘性定位元素
- 是計算後位置屬性為sticky
的元素。
absolute
absolute
定位和overflow
的裁剪類似,它的定位是相對於祖先定位元素的padding box
的。
absolute
相對於最近的position
不為static
的祖先元素定位,如果沒有的話,就像對於html
定位。
當一個元素設定了absolute
時候,它的float
屬性是無效的。
absolute
和float
類似它們有幾個共同點:
- 當元素設定了
position
後也會發生塊狀化
,display
的計算值就是block
或table
。 absolute
會破壞正常的流來實現自己的特性表現,但本身還是受普通的流體元素佈局。absolute
也可以 BFCabsolute
也具有包裹性
無依賴定位
無依賴定位定位指的是,absolute
定位,不依賴left
, right
, top
, bottom
和設定父元素為relative
,來實現元素定位。
absolute
定位元素的位置和沒有設定absolute
時的位置有關。所以我們可以通過調整元素的margin
來調整元素的無依賴定位。
absolute 與 overflow
如果overflow
不是定位元素,同時絕對定位元素和overflow
容器之間也沒有定位元素,則overflow
無法對absolute
元素進行剪裁。
<div style="overflow: hidden;">
<img src="a.jpg" style="position: absolute;">
<!-- 不會被剪裁 -->
</div>
<div style="overflow: hidden; position: relative;">
<img src="a.jpg" style="position: absolute;">
<!-- 被剪裁 -->
</div>
<div style="overflow: hidden;">
<div style="position: relative;">
<img src="a.jpg" style="position: absolute;">
<!-- 被剪裁 -->
</div>
</div>
複製程式碼
如果overflow
的屬性值不是hidden
而是auto
,即使絕對定位元素高寬
比overflow
元素高寬還要大,也都不會出現滾動條。
流體特性
當absolute
元素的left/top/right/bottom
屬性都設定的時候,absolute
元素才真正變成
絕對定位元素。它會格式化元素的寬度和高度。
.box {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
}
複製程式碼
如果box
父定位元素是html
的話,它的寬和高會隨著瀏覽器視窗大小變化而變化。
當絕對定位元素處於流體狀態的時候,各個盒模型相關屬性的解析和普通流體元素都是一
模一樣的,並且可以使用margin:auto
讓絕對定位元素保持居中。
絕對定位元素的margin:auto
規則和普通流體元素的一樣:
- 如果一側定值,一側
auto
,auto
為剩餘空間大小; - 如果兩側均是
auto
,則平分剩餘空間。
.box {
width: 300px; height: 200px;
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
margin: auto;
background: red;
}
複製程式碼
這行程式碼就可以讓box
水平垂直居中。
relative
我們一般用relative
來限制absolute
定位。讓它相對於設定了relative
的祖先容器定位。
relative
是相當於自己當前的位置定位,一般情況下它不會影響到周圍的元素。
當relative
同時設定了left
和right
或top
和bottom
時,它不會和absolute
一樣格式化寬高,而是根據文件流的方向,一個有效而另一個會無效。
fixed
fixed
定位的包含塊只有一個html
根元素,fixed
和absolute
一樣也可使用無依賴定位。
sticky
粘性定位,就好像是relative
和fixed
的結合體。元素在螢幕內,表現為relative
,就要滾出顯示器螢幕的時候,表現為fixed
。
sticky
有以下特點:
sticky
的父級元素的overflow
只能是visible
,否則會沒有效果。- 同一個父容器中的
sticky
元素,如果定位值相等,則會重疊;如果屬於不同父元素,則會擠開原來的元素,形成依次佔位的效果。
inline-block
inline-block
是display
的一個屬性值,它可以讓元素和行內元素一樣在一行顯示,又可以和塊級元素一樣設定寬高。
空隙
使用inline-block
有點小問題,那就是inline-block
元素間有空格或是換行產生了間隙。
<style>
<div></div>
<div></div>
div {
display: inline-block;
width: 100px;
height: 100px;
background: red;
}
</style>
複製程式碼
空格相當於字元,那麼我們可以使用font-size: 0;
去除它們之間的空隙。
除了font-size
我們還可以使用letter-spacing
,它用來設定字元之間的空隙寬度。我們可以設定word-spacing: -1em;
來去除inline-block
之間的空隙。
我們還可以使用word-spacing
,它用來設定單詞間距,它和letter-spacing
相似,我們設定它為負值來去除空隙。
YUI 3 CSS Grids 是這樣去除inline-block
之間的空隙的。
.yui3-g {
letter-spacing: -0.31em; /* webkit */
*letter-spacing: normal; /* IE < 8 */
word-spacing: -0.43em; /* IE < 8 && gecko */
}
.yui3-u {
display: inline-block;
zoom: 1; *display: inline; /* IE < 8 */
letter-spacing: normal;
word-spacing: normal;
vertical-align: top;
}
複製程式碼