層疊樣式表(英文全稱:Cascading Style Sheets)是一種用來(lái)表現(xiàn)HTML或XML等文件樣式的計(jì)算機(jī)語(yǔ)言
1. 正常文檔流(Normal Flow)
沒有用任何CSS來(lái)改變頁(yè)面布局的網(wǎng)頁(yè)怒见,那么網(wǎng)頁(yè)元素就會(huì)排列在一個(gè)正常流(normal flow)之中死遭。在正常流中象浑,元素盒子(boxes)會(huì)基于文檔的寫作模式(writing mode)一個(gè)接一個(gè)地排列招狸。意味著胯究,如果你的寫作模式是水平方向的(句子是從左到右或從右到左書寫)系忙,正常流會(huì)垂直地一個(gè)接一個(gè)排列頁(yè)面的塊級(jí)元素
<div class="container">
<div>1</div>
<p>CSS 能夠?qū)W(wǎng)頁(yè)中元素位置的排版進(jìn)行像素級(jí)精確控制又碌,支持幾乎所有的字體字號(hào)樣式畅卓,擁有對(duì)網(wǎng)頁(yè)對(duì)象和模型樣式編輯的能力</p>
<br/>
<p>從HTML被發(fā)明開始埃难,樣式就以各種形式存在</p>
</div>
正常流是一種最基礎(chǔ)的布局:當(dāng)你為文檔應(yīng)用了CSS莹弊、創(chuàng)建了某些CSS布局,你其實(shí)是讓這些塊做了一個(gè)正常文檔流之外的“事”
1.1. 通過(guò)頁(yè)面結(jié)構(gòu)來(lái)發(fā)揮正常文檔流的優(yōu)勢(shì)
通過(guò)確保你書寫的頁(yè)面具有良好的頁(yè)面結(jié)構(gòu)(well-structured manner)涡尘,你可以最大程度利用正常流所帶來(lái)的優(yōu)勢(shì)忍弛。試想一下,如果瀏覽器中沒有正常流考抄,那么你創(chuàng)建的元素都會(huì)堆積在瀏覽器的右上角细疚。這就意味著你必須指定所有的元素的布局方式。
有了正常流川梅,即使CSS加載失敗了疯兼,用戶仍然能閱讀你的頁(yè)面內(nèi)容;同時(shí)贫途,一些不使用CSS的工具(例如一些閱讀器)會(huì)按照元素在文檔中的位置來(lái)讀取頁(yè)面內(nèi)容吧彪。如果你的內(nèi)容順序和用戶預(yù)期的閱讀順序一致,你就不需要為了將元素調(diào)整到正確的位置而進(jìn)行大量的布局調(diào)整
1.2. 脫離正常文檔流
一旦你有了一個(gè)結(jié)構(gòu)良好的頁(yè)面丢早,你就需要去決定如何利用它并將它變?yōu)槲覀冃枰牟季纸Y(jié)構(gòu)姨裸。這會(huì)涉及到 脫離正常文檔流(moving away from normal flow),后續(xù)的部分內(nèi)容有許多布局可以學(xué)習(xí)使用怨酝。
2. 浮動(dòng)(Float)
float
屬性定義元素在哪個(gè)方向浮動(dòng)傀缩。以往這個(gè)屬性總應(yīng)用于圖像,使文本圍繞在圖像周圍农猬,不過(guò)在 CSS 中赡艰,任何元素都可以浮動(dòng)。浮動(dòng)元素會(huì)生成一個(gè)塊級(jí)框斤葱,而不論它本身是何種元素瞄摊。如果浮動(dòng)非替換元素,則要指定一個(gè)明確的寬度苦掘;否則换帜,它們會(huì)盡可能地窄。
浮動(dòng)被用來(lái)將盒子(box)置于左側(cè)或右側(cè)鹤啡,同時(shí)讓內(nèi)容環(huán)繞其展示惯驼。要讓一個(gè)元素進(jìn)行浮動(dòng),需要為該元素設(shè)置一個(gè)值為left
或right
的float屬性。默認(rèn)值為none
祟牲。
當(dāng)你使某個(gè)元素浮動(dòng)并讓文字環(huán)繞它時(shí)隙畜,內(nèi)容的line box被截?cái)嗔恕H绻阕屢粋€(gè)元素浮動(dòng)说贝,同時(shí)為緊跟著的包含文本的元素設(shè)置一個(gè)背景色议惰,你會(huì)發(fā)現(xiàn)背景色會(huì)出現(xiàn)在浮動(dòng)元素下方
.item{
float: left;
width: 100px;
height: 100px;
background-color: pink;
}
如果你想要在浮動(dòng)元素和環(huán)繞的文本之間創(chuàng)建邊距,你需要給浮動(dòng)元素設(shè)置外邊距乡恕。在文本元素上設(shè)置外邊距只會(huì)讓其相對(duì)于容器縮進(jìn)言询。例如在下面這個(gè)例子中,你就需要為左側(cè)浮動(dòng)的圖片設(shè)置右邊距和下邊距
.item{
margin: 0 30px 30px 0;
}
2.1. 清除浮動(dòng)
一旦你對(duì)一個(gè)元素應(yīng)用了浮動(dòng)傲宜,所有接下來(lái)的元素都會(huì)環(huán)繞它直到內(nèi)容處于它下方且開始應(yīng)用正常文檔流运杭。如果你想要避免這種情況,可以手動(dòng)去清除浮動(dòng)函卒。
當(dāng)你不想要某個(gè)元素受到其之前的浮動(dòng)元素影響時(shí)辆憔,為其添加clear: both
屬性即可。使用left值可以清除左浮動(dòng)效果报嵌,right值為右浮動(dòng)虱咧,both則會(huì)清除左右浮動(dòng)。
但是锚国,當(dāng)你發(fā)現(xiàn)在容器內(nèi)有了一個(gè)浮動(dòng)元素彤钟,同時(shí)容器文本內(nèi)容過(guò)短時(shí)就會(huì)出現(xiàn)問(wèn)題。文本盒子會(huì)被繪制在浮動(dòng)元素下跷叉,然后接下來(lái)的部分會(huì)以正常流繪制在其后逸雹。
為了避免這種情況,我們需要為容器中某個(gè)元素應(yīng)用clear屬性云挟。我們可以在容器最后添加一個(gè)空元素并設(shè)置clear屬性梆砸。但是在某些情況下可能無(wú)法使用這種方式。因此园欣,比較常見的清除浮動(dòng)的方案是:在容器內(nèi)添加一個(gè)CSS偽元素帖世,并將其clear屬性設(shè)置為both。
.container p::after{
content: "";
display: block;
clear: both;
}
2.2. 塊級(jí)格式化上下文(Block Formatting Context)
清除浮動(dòng)的另一個(gè)方法是在容器內(nèi)創(chuàng)建BFC沸枯。一個(gè)BFC元素完全包裹住了它內(nèi)部的所有元素日矫,包括內(nèi)部的浮動(dòng)元素,保證浮動(dòng)元素不會(huì)超出其底部绑榴。創(chuàng)建BFC的方式有很多種哪轿,其中最常用的一種清除浮動(dòng)的方式是為元素設(shè)置除visible(默認(rèn))之外的overflow: auto
屬性值
像上面這樣使用overflow一般情況下是有效的。然而翔怎,在某些情況下窃诉,這可能會(huì)帶來(lái)一些陰影的截?cái)嗷蚴欠穷A(yù)期的滾動(dòng)條杨耙。同時(shí)它也使你的CSS變得不那么直觀:為了使清除浮動(dòng)的意圖更加直觀,并且避免BFC的負(fù)面影響飘痛,你可以使用flow-root作為display屬性的值珊膜。display: flow-root
做的唯一的一件事就是去創(chuàng)建一個(gè)BFC,因此可以避免其他創(chuàng)建BFC方法帶來(lái)的問(wèn)題宣脉。
2.3. 浮動(dòng)的一些遺留用法
在新的布局方式出現(xiàn)以前车柠,float經(jīng)常會(huì)被用來(lái)創(chuàng)建多欄布局。我們會(huì)給一系列元素設(shè)置寬度并且將它們一個(gè)接一個(gè)進(jìn)行浮動(dòng)塑猖。通過(guò)為浮動(dòng)元素設(shè)置一些精細(xì)的百分比大小可以創(chuàng)建類似網(wǎng)格的效果竹祷。
我不建議在當(dāng)下仍然過(guò)度地使用這種方法。但是萌庆,在現(xiàn)有的網(wǎng)站中,這種方式仍然會(huì)存在許多年币旧。因此践险,當(dāng)你碰到一個(gè)頁(yè)面里面到處是float的應(yīng)用,可以確定它就是用的這種技術(shù)吹菱。
3. 定位(Positioning)
想要把一個(gè)元素從正常流中移除巍虫,或者改變其在正常文檔流中的位置,可以使用CSS中的position屬性鳍刷。當(dāng)處于正常文檔流時(shí)规揪,元素的position屬性為static诗鸭。在塊級(jí)維度上元素會(huì)一個(gè)接一個(gè)排列下去,當(dāng)你滾動(dòng)頁(yè)面時(shí)元素也會(huì)隨著滾動(dòng)。
當(dāng)你改變?cè)氐膒osition屬性時(shí)欠雌,通常情況下你也會(huì)設(shè)置一些偏移量來(lái)使元素相對(duì)于參照點(diǎn)進(jìn)行一定的移動(dòng)。不同的position值會(huì)產(chǎn)生不同的參照點(diǎn)业筏。
3.1. 相對(duì)定位(relative postioning)
如果一個(gè)元素具有屬性position: relative
姨俩,那么它偏移的參照位是其原先在正常文檔流中的位置。你可以使用top北戏、left负芋、bottom和right屬性來(lái)相對(duì)其正常流位置進(jìn)行移動(dòng)。
注意嗜愈,頁(yè)面上的其他元素并不會(huì)因該元素的位置變化而受到影響旧蛾。該元素在正常流中的位置會(huì)被保留,因此你需要自己去處理一些元素內(nèi)容覆蓋的情況蠕嫁。
<div class="container">
<p>P1</p>
<div class="item">1</div>
<p>P2</p>
</div>
<style>
.item{
width: 50px;
height: 50px;
background-color: pink;
position: relative;
bottom: 20px;
}
</style>
3.2. 絕對(duì)定位(absolute postioning)
給一個(gè)元素設(shè)置position: absolute
屬性可以將其完全從正常流中移除锨天。其原本占據(jù)的空間也會(huì)被移除。該元素會(huì)定位會(huì)相對(duì)于視口容器剃毒,除非其某個(gè)祖先元素也是定位元素(position值不為static)绍绘。
因此,當(dāng)你為某個(gè)元素設(shè)置position: absolute時(shí),首先發(fā)生的變化是該元素會(huì)定位在視口的左上角陪拘。你可以通過(guò)設(shè)置top厂镇、left、bottom和right偏移量屬性來(lái)將元素移動(dòng)到你想要的位置
通常情況下你并不希望元素相對(duì)于視口進(jìn)行定位左刽,而是相對(duì)于容器元素捺信。在這種情況下,你需要為容器元素設(shè)置一個(gè)除了默認(rèn)static之外的值欠痴。
由于給一個(gè)元素設(shè)置position: relative并不會(huì)將其從正常流中移除迄靠,所以通常這是一個(gè)不錯(cuò)的選擇。給你想要相對(duì)的容器元素設(shè)置position : relative喇辽,就可以讓絕對(duì)定位的元素相對(duì)其進(jìn)行偏移掌挚。
.item{
width: 50px;
height: 50px;
background-color: pink;
position: absolute;
top: 20px;
left: 50px;
}
3.3. 固定定位(fixed positioning)
大多數(shù)情況下,position: fixed
的元素會(huì)相對(duì)于視口定位菩咨,并且會(huì)從正常文檔流中被移除吠式,不會(huì)保留它所占據(jù)的空間。當(dāng)頁(yè)面滾動(dòng)時(shí)抽米,固定的元素會(huì)留在相對(duì)于視口的位置特占,而其他正常流中的內(nèi)容則和通常一樣滾動(dòng)。
當(dāng)你想要一個(gè)固定導(dǎo)航欄一直停留在屏幕上時(shí)這會(huì)非常有效云茸。和其他的position值一樣是目,這也可能會(huì)造成一些元素被遮擋,需要小心保證頁(yè)面內(nèi)容的可讀而不會(huì)被固定元素遮擋标捺。
為了使一個(gè)固定定位的元素不相對(duì)于視口進(jìn)行定位懊纳,你需要為容器元素設(shè)置transform、perspective亡容、filter三個(gè)屬性之一(不為默認(rèn)值none)长踊。這樣固定的元素就會(huì)相對(duì)于該塊級(jí)元素偏移,而非視口萍倡。
.item{
width: 50px;
height: 50px;
background-color: pink;
position: fixed;
top: 20px;
left: 30px;
}
3.4. STICKY 定位
設(shè)置position: sticky
會(huì)讓元素在頁(yè)面滾動(dòng)時(shí)如同在正常流中身弊,但當(dāng)其滾動(dòng)到相對(duì)于視口的某個(gè)特定位置時(shí)就會(huì)固定在屏幕上,如同fixed一般列敲。這個(gè)屬性值是一個(gè)較新的CSS屬性阱佛,在瀏覽器兼容性上會(huì)差一些,但在不兼容的瀏覽器中會(huì)被忽略并會(huì)退到正常的滾動(dòng)情況戴而。
下面的代碼展示了如何創(chuàng)建一個(gè)非常流行導(dǎo)航欄效果:導(dǎo)航欄會(huì)隨著頁(yè)面滾動(dòng)凑术,而當(dāng)導(dǎo)航欄滾動(dòng)到頁(yè)面頂部時(shí)則會(huì)固定在頂部位置。
.item{
width: 50px;
height: 50px;
background-color: pink;
position: sticky;
top: 0;
width: 100%;
}
4. 彈性布局(Flex Layout)
彈性盒子(Flexbox)布局是一種為一維布局而設(shè)計(jì)的布局方法所意。一維的意思是你希望內(nèi)容是按行或者列來(lái)布局淮逊。你可以使用display: flex
來(lái)將元素變?yōu)閺椥圆季执呤住T撊萜鞯闹苯幼釉貢?huì)變?yōu)閺椥皂?xiàng)(flex item),并按行排列泄鹏。
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<style>
.container {
border: 5px solid burlywood;
border-radius: .5em;
background-color: lightgrey;
padding: 10px;
display: flex;
}
.item {
width: 50px;
height: 50px;
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
</style>
4.1. 彈性盒子的軸(axes)
在上面的例子中郎任,我們會(huì)稱彈性項(xiàng)在行內(nèi)是從起始位置開始排列,而不是說(shuō)它們是左對(duì)齊备籽。這些元素會(huì)按行排列是因?yàn)槟J(rèn)的flex-direction值為row舶治,row代表了文本的行文方向。由于我們工作的環(huán)境是英文(中文也是如此)车猬,一種自左向右的語(yǔ)言霉猛,行的開始位置就是在左邊,因此我們的彈性項(xiàng)也是從左邊開始的珠闰。因此flex-direction的值被定義為彈性盒子的主軸(main axis)惜浅。
交叉軸(cross axis)則是和主軸垂直的一條軸。如果你的flex-direction是row并且彈性項(xiàng)是按照行內(nèi)方向排列的伏嗜,那么交叉軸就是塊級(jí)元素的排列方向坛悉。如果flex-direction是column那么彈性項(xiàng)就會(huì)以塊級(jí)元素排列的方向排布,然后交叉軸就會(huì)變?yōu)閞ow阅仔。設(shè)置flex-direction: column
效果如下:
4.2. 方向和次序
彈性盒子模型讓我們可以通過(guò)為flex-direction屬性設(shè)置row-reverse或column-reverse值來(lái)改變主軸上彈性項(xiàng)的方向吹散。當(dāng)然弧械,你也可以通過(guò)order屬性來(lái)改變某一個(gè)彈性項(xiàng)的順序八酒。但是要特別注意,這可能會(huì)給那些通過(guò)鍵盤(而非鼠標(biāo)或觸屏)訪問(wèn)你的網(wǎng)站的用戶帶來(lái)一些麻煩刃唐,因?yàn)閠ab的順序是頁(yè)面內(nèi)元素在源碼中的順序而非顯示順序羞迷。設(shè)置flex-direction: row-reverse
效果如下:
4.3. 一些Flex的屬性
這些flex的屬性是用來(lái)控制彈性項(xiàng)在主軸上空間大小的。這三個(gè)屬性是:
flex-grow / flex-shrink / flex-basis
通郴ⅲ可以使用它們的簡(jiǎn)寫形式:flex: 1 1 200px
衔瓮;第一個(gè)值代表flex-grow,第二個(gè)是flex-shrink抖甘,而第三個(gè)則是flex-basis热鞍。
flex-basis會(huì)為彈性項(xiàng)設(shè)置未拉伸和壓縮時(shí)的初始大小。在上面的例子中衔彻,大小是200px薇宠,因此我們會(huì)給每個(gè)項(xiàng)200px的空間大小。但是大多數(shù)情況下容器元素大小不會(huì)正好被分為許多200px大小的項(xiàng)艰额,而是可能有一些不足或剩余空間澄港。flex-grow和flow-shrink屬性允許我們在容器大小不足或有空余時(shí)控制各個(gè)彈性項(xiàng)的大小。
如果flex-grow的值是任意的正數(shù)柄沮,那么彈性項(xiàng)會(huì)被允許拉伸來(lái)占據(jù)更多的空間回梧。因此废岂,在上面的例子中,當(dāng)各項(xiàng)被設(shè)為200px后狱意,所有多余的空間會(huì)被每個(gè)彈性項(xiàng)平分并填滿湖苞。
如果flex-shrink的值為任意的正數(shù),那么當(dāng)彈性項(xiàng)被設(shè)置了flex-basis后髓涯,元素溢出容器時(shí)會(huì)進(jìn)行收縮袒啼。在上面這個(gè)CSS的例子中,如果容器空間不足纬纪,每個(gè)彈性項(xiàng)會(huì)等比例縮放以適應(yīng)容器的大小蚓再。
flex-grow和flex-shrink的值可以是任意的正數(shù)。一個(gè)具有較大flex-grow值的彈性項(xiàng)會(huì)在容器有剩余空間時(shí)拉伸更大的比例包各;而一個(gè)具有更大flex-shrink值的項(xiàng)則會(huì)在容器空間不足時(shí)被壓縮的更多摘仅。
.item {
flex: 1 1 200px;
width: 200px;
height: 50px;
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.container :nth-child(1) {
flex: 10 1 200px;
}
5. 網(wǎng)格布局(grid layout)
CSS網(wǎng)格布局(grid layout)是一種用來(lái)進(jìn)行二維布局的技術(shù)。二維(two-dimesional)意味著你希望按照行和列來(lái)排布你的內(nèi)容问畅。和彈性盒子類似娃属,網(wǎng)格布局也需要設(shè)置一個(gè)display值。你可以為容器元素設(shè)置display: grid
护姆,并且使用grid-template-columns
和grid-template-rows
屬性來(lái)控制網(wǎng)格中的行與列矾端。
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
<style>
.container {
width: 780px;
border: 5px solid burlywood;
border-radius: .5em;
background-color: lightgrey;
padding: 10px;
display: grid;
grid-template-columns: 200px auto auto;
grid-template-rows: 80px 80px;
}
.item {
width: 200px;
height: 50px;
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
</style>
這段CSS會(huì)創(chuàng)建一個(gè)行列元素大小固定的網(wǎng)格。不過(guò)這也許并不是你希望的卵皂。默認(rèn)值為auto秩铆,你可以認(rèn)為這代表了“讓格子盡可能的大”。如果你每沒有指定行(row track)的大小灯变,所有添加進(jìn)來(lái)的行內(nèi)容大小都會(huì)被置為auto殴玛。一種常用的模式是為網(wǎng)格制定列寬度,但是允許網(wǎng)格按需添加行添祸。
你可以使用任意的長(zhǎng)度單位或時(shí)百分比來(lái)設(shè)置行與列滚粟,同時(shí)你可以使用為網(wǎng)格系統(tǒng)所創(chuàng)造的新的單位——fr。fr是一種彈性單位刃泌,它可以指定網(wǎng)格容器內(nèi)的空間被如何劃分凡壤。
網(wǎng)格會(huì)替你計(jì)算與分配空間,你不需要去計(jì)算元素的百分比去適應(yīng)容器大小耙替。在下面這個(gè)例子中亚侠,我們使用fr來(lái)創(chuàng)建網(wǎng)格的列,這使得網(wǎng)格的列可以自適應(yīng)林艘。同時(shí)我們還使用了grid-gap
來(lái)保證元素間的間距(關(guān)于網(wǎng)格內(nèi)元素與的間距會(huì)在“對(duì)齊”這一部分詳細(xì)介紹)盖奈。
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 20px;
5.1. 關(guān)于網(wǎng)格的一些術(shù)語(yǔ)
網(wǎng)格系統(tǒng)總是有兩個(gè)軸:inline axis
表示頁(yè)面中文字的文字排列的方向,block axis
表示頁(yè)面中塊級(jí)元素的排列方向狐援。
一個(gè)被設(shè)置為display: grid
的元素就是所謂的網(wǎng)格容器钢坦。在網(wǎng)格容器中會(huì)有網(wǎng)格線(grid line)究孕,網(wǎng)格線就是你在指定grid-template-columns
和grid-template-rows
時(shí)網(wǎng)格中行列所生成的。網(wǎng)格中的最小單位(也就是被四條網(wǎng)格線截取生成的區(qū)域)被成為網(wǎng)格單元格(grid cell)爹凹,進(jìn)一步的厨诸,由若干個(gè)單元格組成的矩形區(qū)域被成為網(wǎng)格區(qū)域(grid area)。
5.2. 網(wǎng)格的自動(dòng)排列規(guī)則
一旦你創(chuàng)建了網(wǎng)格禾酱,那么網(wǎng)格容器的直接子元素就會(huì)開始將它們自己一個(gè)一個(gè)地放置在網(wǎng)格的單元格中微酬。子元素的放置是依據(jù)網(wǎng)格的自動(dòng)排列規(guī)則(auto-placement rule)。這些規(guī)則確保了網(wǎng)格內(nèi)元素是被安排在各個(gè)空的單元格中颤陶,而不會(huì)彼此遮蓋颗管。
網(wǎng)格中任何沒有被進(jìn)行定位的直接子元素都會(huì)根據(jù)自動(dòng)排列規(guī)則進(jìn)行放置。在下面這個(gè)列子中滓走,我讓每三個(gè)元素中的第一個(gè)占據(jù)兩行垦江,但仍然從起始行開始去自動(dòng)排列(自動(dòng)伸縮需元素需去除width&height
屬性)。
.container :nth-child(1){
grid-row-end: span 2;
}
5.3. 基于行/列的基本定位方法
定位網(wǎng)格元素最簡(jiǎn)單的方式是使用基于行/列(line)的定位方法搅方,只需告訴瀏覽器從哪一排到哪一排來(lái)進(jìn)行合并比吭。例如,如果你需要一個(gè)2*2的網(wǎng)格區(qū)域姨涡,你可以將指定元素從第一行開始到第三行衩藤、從第一列開始到第三列,這樣就可以覆蓋到四個(gè)單元格涛漂。
.item {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 3;
}
可簡(jiǎn)寫為:
.item {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
你也可以讓網(wǎng)格項(xiàng)(grid item)占據(jù)同一個(gè)單元格赏表。支持一些內(nèi)容間會(huì)覆蓋的設(shè)計(jì)。網(wǎng)格項(xiàng)會(huì)像通常網(wǎng)頁(yè)中的元素那樣疊起來(lái)怖喻,在html源碼中下面的網(wǎng)格項(xiàng)會(huì)疊在其他元素上面底哗。你仍然可以用z-index來(lái)控制它的堆疊順序
.container :nth-child(1){
grid-column: 1 / 3;
grid-row: 2;
z-index: 100;
}
.container :nth-child(4){
grid-row: 1/3;
grid-column: 2;
background-color: rgba(11,41,97,.3);
}
5.4. 通過(guò)命名區(qū)域來(lái)定位元素
你可以通過(guò)命名區(qū)域(named areas)來(lái)定位網(wǎng)格中的元素岁诉。要是用這種方式锚沸,你需要給每個(gè)元素一個(gè)名字,然后通過(guò)grid-template-areas
屬性的值來(lái)描述布局方式涕癣。
使用這種方式有幾個(gè)需要注意的點(diǎn)哗蜈。如果你想要合并一些單元格作為你的網(wǎng)格項(xiàng),你需要重復(fù)元素的名字坠韩。網(wǎng)格區(qū)域需要能形成一個(gè)完整的矩形 —— 每個(gè)單元格都需要被填入一個(gè)值距潘。如果你想要空出某些單元格,那就需要使用.這個(gè)值只搁。例如在下面的CSS里我將最右下角的單元格留空音比。
grid-template-areas:
"a a b"
"a c c";
6. 顯示順序和文檔順序(visual and document order)
在文章的最開始,我建議你以從上到下的閱讀順序來(lái)組織你的文檔順序氢惋,這樣會(huì)有助于可讀性和CSS的布局方式洞翩。從我們關(guān)于彈性盒子和CSS網(wǎng)格的簡(jiǎn)短介紹來(lái)看稽犁,你可以發(fā)現(xiàn)用這些布局方法可能會(huì)極大地改變頁(yè)面展示的元素在文檔中的順序。這可能會(huì)導(dǎo)致一個(gè)隱含的問(wèn)題骚亿。
在一些非可視化的應(yīng)用場(chǎng)景中已亥,瀏覽器會(huì)遵循文檔源碼來(lái)進(jìn)行使用。因此来屠,屏幕閱讀器會(huì)讀取文檔的順序虑椎,此外使用鍵盤tab鍵來(lái)瀏覽的用戶訪問(wèn)文檔的順序是基于源碼的順序,而不是元素展示的順序俱笛。許多屏幕閱讀器的用戶并非完全失明捆姜,他們可能在使用屏幕閱讀器的同時(shí)也能夠看到這些元素在文檔的哪個(gè)部分。在這些情況下迎膜,當(dāng)與源碼進(jìn)行對(duì)比時(shí)娇未,這種混亂的頁(yè)面展現(xiàn)可能會(huì)令人充滿迷惑。
當(dāng)你改變了元素在文檔中原來(lái)的順序時(shí)星虹,一定確保知道自己在做什么零抬。如果你發(fā)現(xiàn)你自己正在CSS中重新排序你的元素,你應(yīng)該去回頭看看是否要重新組織你的頁(yè)面元素宽涌。你可以通過(guò)使用tab訪問(wèn)來(lái)測(cè)試一下你的頁(yè)面平夜。
7. 盒模型的生成(box generation)
你寫在網(wǎng)頁(yè)里的任何東西都會(huì)生成一個(gè)盒子(box),這篇文章討論的所有東西其實(shí)都是如何能夠使用CSS來(lái)按照你的設(shè)計(jì)布局這些盒子卸亮。然而忽妒,在某些情況下,你可能根本不想創(chuàng)建一個(gè)盒子兼贸。有兩個(gè)display的屬性值會(huì)幫你處理這種情況段直。
7.1. 不生成盒子或內(nèi)容(display: none)
如果你希望元素以及它所有的內(nèi)容(包括所有子元素)都不會(huì)生成,你可以使用display: none
溶诞。這樣元素就不會(huì)被展示鸯檬,并且不會(huì)保留其本該占有的空間。
7.2 不生成該元素螺垢,但是生成其所有子元素(display: contents)
display: content是display的一個(gè)新的屬性值喧务。為一個(gè)元素應(yīng)用display: content
屬性會(huì)導(dǎo)致其自身的盒子不生成但所有的子元素都會(huì)照常生成。這有什么用呢枉圃?試想一下功茴,如果你希望一個(gè)彈性布局或網(wǎng)格布局中的非直接子元素能應(yīng)用這些布局,這就會(huì)非常有用孽亲。
在下面這個(gè)例子里坎穿,第一個(gè)彈性項(xiàng)包含了兩個(gè)子元素,由于它被設(shè)為display: contents
,它的盒子不會(huì)生成并且它的兩個(gè)子元素會(huì)成為彈性項(xiàng)玲昧,并被當(dāng)作彈性盒子容器的直接子元素來(lái)布局犯祠。
<div class="container">
<div class="item">
<div class="subitem">A</div>
<div class="subitem">B</div>
</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<style>
.container {
border: 5px solid burlywood;
border-radius: .5em;
background-color: lightgrey;
padding: 10px;
display: flex;
}
.item {
width: 200px;
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
</style>
增加以下樣式后:
.subitem {
width: 200px;
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.container .item:first-child{
display: contents;
}
8. 對(duì)齊
在以前,要實(shí)現(xiàn)對(duì)齊往往會(huì)用到一些很"tricky"的方式酌呆,并且能夠使用的方法也非常有限衡载。隨著CSS盒模型對(duì)齊(box alignment module)的出現(xiàn),這一切都發(fā)生了變化隙袁。你將會(huì)使用它來(lái)控制網(wǎng)格容器與彈性盒子容器中的對(duì)齊痰娱。未來(lái)其他的各種布局方法都會(huì)應(yīng)用這些對(duì)齊屬性。盒模型對(duì)齊(box alignment specification)規(guī)范中的一系列詳細(xì)屬性如下:
justify-content
align-content
place-content
justify-items
align-items
place-items
justify-self
align-self
place-self
row-gap
column-gap
gap
由于不同的布局模型有不同的特性菩收,因此用于不同布局模型的對(duì)齊屬性會(huì)有一些表現(xiàn)上的差異梨睁。讓我們來(lái)看看在一些簡(jiǎn)單的網(wǎng)格與彈性布局中對(duì)齊是如何工作的。
align-items
和justify-items
屬性相對(duì)是align-self
和justify-self
屬性的一種批量形式娜饵。這些屬性會(huì)控制與元素在其網(wǎng)格區(qū)域(grid area)中的對(duì)齊情況坡贺。
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
<style>
.container {
border: 5px solid burlywood;
border-radius: .5em;
background-color: lightgrey;
padding: 10px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: minmax(100px, auto);
grid-gap: 20px;
align-items: center;
justify-items: start;
}
.item {
width: 200px;
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.container :nth-child(5){
align-self: end;
justify-self: end;
}
</style>
align-content
和justify-content
屬性則會(huì)對(duì)網(wǎng)格中的行/列(tracks)進(jìn)行對(duì)齊控制(網(wǎng)格容器中需要在排列完行/列元素后有多余的空間)。
align-content: space-between;
justify-content: end;
在彈性盒子中箱舞,align-items
和align-self
用來(lái)解決交叉軸上的對(duì)齊問(wèn)題遍坟,而justify-content
則用于解決主軸上空間的分配。
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<style>
.container {
border: 5px solid burlywood;
border-radius: .5em;
background-color: lightgrey;
padding: 10px;
display: flex;
height: 200px;
justify-content: space-between;
align-items: flex-end;
}
.item {
width: 200px;
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.container :nth-child(3){
align-self: stretch;
}
</style>
在交叉軸上晴股,把彈性行(flex line)和額外空間包裹在彈性容器中之后愿伴,你就可以使用align-content
了。
8.1. 行/列的間隔
一個(gè)多欄布局具有column-gap
屬性电湘,到目前位置隔节,網(wǎng)格布局具有grid-column-gap
、grid-row-gap
和grid-gap
寂呛。這些現(xiàn)在都被從grid標(biāo)準(zhǔn)中刪除而被添加進(jìn)盒模型對(duì)齊中了怎诫。與此同時(shí),grid-的前綴屬性被重命名為column-gap
贷痪、row-gap
和gap
幻妓。瀏覽器會(huì)將帶有前綴的屬性換為新的重命名屬性,所以如果你在目前的代碼中使用兼容性更好的老名字也不用擔(dān)心呢诬。
重命名意味著這些屬性也能被應(yīng)用于其他布局方法涌哲,一個(gè)明顯的備選就是彈性盒子胖缤。雖然目前沒有瀏覽器支持盒子模型中的gap屬性尚镰,但是在未來(lái)我們應(yīng)該可以使用column-gap
和row-gap
來(lái)創(chuàng)建彈性項(xiàng)目元素間的間距。
9. 多欄布局(多列布局)
多欄布局(multi-column layout)是一種支持創(chuàng)建多欄的布局類型哪廓,如同報(bào)紙上那樣狗唉。每一塊都被分割成欄(column),你會(huì)按照塊方向在欄中往下讀然后會(huì)在回到下一欄的頂部涡真。然而用這種方式閱讀在網(wǎng)頁(yè)內(nèi)容中并不總是有效分俯,因?yàn)槿藗儾⒉幌肴プ対L動(dòng)條滾動(dòng)來(lái)肾筐、滾動(dòng)去地去閱讀。當(dāng)需要展示少部分內(nèi)容缸剪、折疊一組復(fù)選框或者其他一些小的UI組件時(shí)會(huì)非常有用吗铐。
當(dāng)展示一組高度不同的卡片或產(chǎn)品時(shí)多欄布局也非常有用。
9.1. 設(shè)置欄的寬度
要設(shè)置一個(gè)最有的欄寬杏节,并通知瀏覽器依此寬度展示盡可能多的欄可以使用下面的CSS:
.container {
column-width: 300px;
}
這會(huì)創(chuàng)建盡可能多的300px的欄唬渗,所有剩下的空間會(huì)被所有欄共享。因此奋渔,除非空間被劃分為300px時(shí)沒有剩余镊逝,否則你的欄會(huì)比300px稍多一些。
9.2. 設(shè)置欄的數(shù)目
除了設(shè)置寬度嫉鲸,你可以使用column-count來(lái)設(shè)置欄的數(shù)目撑蒜。在這種情況下,瀏覽器會(huì)將空間均分給你需要的數(shù)目的欄玄渗。
.container {
column-count: 3;
}
如果你同時(shí)添加了column-width
和column-count
座菠,那么column-count
屬性會(huì)作為一個(gè)最大值限制。在下面的代碼里藤树,欄會(huì)被添加直到達(dá)到三個(gè)辈灼,此時(shí)任何額外的空間都會(huì)被分給三欄,即使空間足夠成為一個(gè)額外的新欄也榄。
.container {
column-width: 300px;
column-count: 3;
}
9.3. 間距和欄規(guī)則
你無(wú)法為單個(gè)欄盒子添加外邊距和內(nèi)邊距巡莹,需要用column-gap
屬性來(lái)設(shè)置間距。如果你不具體指定column-gap
的值甜紫,它會(huì)默認(rèn)為1em
來(lái)防止欄間碰撞降宅。這和其他布局方法中column-gap
的行為不一樣,其他布局中默認(rèn)為0囚霸。你可以在間距上使用任意的長(zhǎng)度單元腰根,包括0(如果你不希望有欄間距)。
column-rule
屬性讓你有能力向兩欄間*添加規(guī)則拓型。它是column-rule-width
额嘿、column-rule-color
和column-rule-style
的簡(jiǎn)寫形式,可border行為類似劣挫。注意册养,一個(gè)規(guī)則自身不會(huì)占用任何空間。它會(huì)占據(jù)在間距的頂部压固,從而增加或減少那些你設(shè)置column-gap
的規(guī)則與內(nèi)容間的空間球拦。
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3<br/>33</div>
</div>
<style>
.container {
border: 5px solid burlywood;
border-radius: .5em;
background-color: lightgrey;
padding: 10px;
column-width: 240px;
column-gap: 20px;
column-rule: 4px dotted #000;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
</style>
9.4. 允許元素橫跨多欄
你可以使用column-span
屬性讓多欄容器內(nèi)的元素橫跨多欄,類似通欄。
當(dāng)column-span出現(xiàn)時(shí)坎炼,多欄容器分欄會(huì)在這個(gè)元素上放停下愧膀,因此,容器里的內(nèi)容會(huì)在元素上方形成多欄樣式谣光,然后在橫跨元素(spanning element)的下方形成一組新的欄盒子(column box)檩淋。
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3<br/>33</div>
<div class="special">header</div>
<div class="item">2</div>
<div class="item">3<br/>33</div>
</div>
<style>
.container {
border: 5px solid burlywood;
border-radius: .5em;
background-color: lightgrey;
padding: 10px;
column-width: 240px;
column-gap: 20px;
column-rule: 4px dotted #000;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.special{
column-span: all;
background-color: rgba(193,225,237,.6);
border:2px solid rgba(193,225,237,.6);
margin: 1em 0;
padding: .5em;
}
</style>
你只可以使用column-span: all
或column-span: none
,并不能讓元素橫跨某幾個(gè)欄(非通欄)萄金。在文章寫作時(shí)狼钮,F(xiàn)irefox還不支持column-span屬性。
10. 碎片化(Fragmentation)
多欄布局是碎片化(fragmentation)的一個(gè)例子捡絮,頁(yè)面內(nèi)容會(huì)被拆分成欄熬芜。這和打印時(shí)內(nèi)容被分到不同頁(yè)非常類似。這個(gè)過(guò)程是碎片化規(guī)范(Fragmentation specification)處理的福稳。這個(gè)規(guī)范包括了一些幫助控制內(nèi)容切分的屬性涎拉。
11. 布局類型選擇
大多數(shù)的網(wǎng)頁(yè)會(huì)混合使用多種布局類型。各布局規(guī)范都準(zhǔn)確定義了它們之間是如何相互作用的的圆。例如鼓拧,你可能會(huì)在網(wǎng)格布局的網(wǎng)格項(xiàng)中使用彈性布局。一些彈性容器可能具有定位屬性或浮動(dòng)越妈。這些規(guī)范根據(jù)最優(yōu)的布局方式已經(jīng)包含了布局模型的混合使用季俩。在這篇指南中,我嘗試概述了這種布局類型的基本使用方式梅掠,來(lái)幫助你了解實(shí)現(xiàn)一個(gè)效果可能的最好方法酌住。
然而,別害怕去運(yùn)用多種方式來(lái)實(shí)現(xiàn)布局設(shè)計(jì)阎抒。擔(dān)心你的選擇會(huì)不會(huì)造成實(shí)際問(wèn)題的情況比你想象中要少很多酪我。所以請(qǐng)?jiān)陂_始就組織好你的文檔結(jié)構(gòu),并且注意你文檔內(nèi)容的可視展示順序且叁。剩下的大部分工作就是在瀏覽器中試試你的布局方式是否符合預(yù)期。