前言
溫馨提示:本文較長洞慎,圖片較多丹弱,本來是想寫一篇 CSS 布局方式的庐船,但是奈何 CSS 布局方式種類太多并且實(shí)現(xiàn)方法太多昆庇,所以本文主要是介紹 flex 布局和 grid 布局,以及 CSS 常見的居中方式和兩種經(jīng)典的布局方式“圣杯布局”和“雙飛翼布局”揩晴。想到哪寫到哪勋陪,請各位見諒。
傳統(tǒng)盒模型布局方式
我們的傳統(tǒng)布局方式就是通過盒模型诅愚,使用 display
屬性(文檔流布局) + position
屬性(定位布局) + float
屬性(浮動布局)。這個大家都比較熟悉劫映,沒有掌握的同學(xué)再去惡補(bǔ)一下基礎(chǔ)
文檔流布局
這是最基本的布局方式违孝,就是按照文檔的順序一個一個顯示出來,塊元素獨(dú)占一行泳赋,行內(nèi)元素共享一行雌桑,這個相信大家都比較熟悉了,就不再贅述了
浮動布局
浮動方式布局就是使用 float
屬性祖今,使元素脫離文檔流校坑,浮動起來。這個大家也比較熟悉千诬,就不再贅述了耍目。
定位布局
我們也可以通過 position
屬性來進(jìn)行定位,這個大家也比較熟悉了徐绑,就不再贅述了制妄。
flex 布局
僅僅通過上述的三種布局方式還是有一些缺陷,比如我們不能只使用一個屬性來實(shí)現(xiàn)垂直居中布局泵三,所以就產(chǎn)生了第四種布局方式:flex 布局耕捞。
什么是 flex 布局
2009年,W3C 提出了一種新的方案----Flex 布局烫幕,可以簡便俺抽、完整、響應(yīng)式地實(shí)現(xiàn)各種頁面布局较曼。目前磷斧,它已經(jīng)得到了所有瀏覽器的支持,這意味著捷犹,現(xiàn)在就能很安全地使用這項(xiàng)功能弛饭。
Flex 是 Flexible Box 的縮寫,意為"彈性布局"萍歉,用來為盒狀模型提供最大的靈活性侣颂。
flex 是一種新型的布局方式,使用該布局方式可以實(shí)現(xiàn)幾乎所有你想要的效果枪孩。但是要注意其瀏覽器的兼容性憔晒,flex 只支持 ie 10+藻肄,所有還是要根據(jù)你的項(xiàng)目情況使用(沒錯,我們要求至少 ie 9拒担,(?_?))嘹屯。
使用 flex 布局
flex 的使用方法很簡單,只需要將其 display
屬性設(shè)置為 flex
就可以从撼,也可以設(shè)置行內(nèi)的 flex州弟,記得 Webkit 內(nèi)核的瀏覽器,必須加上 -webkit
前綴低零。注意呆馁,設(shè)為 Flex 布局以后,子元素的 float
毁兆、clear
和 vertical-align
屬性將失效浙滤。
.ele{
display: -webkit-flex;
display: flex;
display: inline-flex;
display: -webkit-inline-flex;
}
在 flex 中,最核心的概念就是容器和軸气堕,所有的屬性都是圍繞容器和軸設(shè)置的纺腊。其中,容器分為父容器和子容器茎芭。軸分為主軸和交叉軸(主軸默認(rèn)為水平方向揖膜,方向向右,交叉軸為主軸順時針旋轉(zhuǎn) 90°)梅桩。
在使用 flex 的元素中壹粟,默認(rèn)存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)
主軸開始的位置稱為 main start
,主軸結(jié)束的位置稱為 main end
宿百。
同理趁仙,交叉軸開始的位置稱為 cross start
,交叉軸結(jié)束的位置稱為 cross end
垦页。
在使用 flex 的子元素中雀费,占據(jù)的主軸空間叫做 main size
,占據(jù)的交叉軸空間叫做 cross size
痊焊。
父容器屬性
父容器上有六個屬性
- flex-direction:主軸的方向盏袄。
- flex-wrap:超出父容器自容器的排列樣式。
- flex-flow:
flex-direction
屬性和flex-wrap
屬性的簡寫形式薄啥。 - justify-content:子容器在主軸的排列方向辕羽。
- align-items:子容器在交叉軸的排列方向。
- align-content:多根軸線的對齊方式垄惧。
<span id="flex-direction">flex-direction 屬性</span>
flex-direction 屬性決定主軸的方向(主軸的方向不一定是水平的刁愿,這個屬性就是設(shè)置主軸的方向,主軸默認(rèn)是水平方向赘艳,從左至右酌毡,如果主軸方向設(shè)置完畢克握,那么交叉軸就不需要設(shè)置蕾管,交叉軸永遠(yuǎn)是主軸順時針旋轉(zhuǎn) 90°)枷踏。
.ele {
flex-direction: row; // 默認(rèn)值,主軸為水平方向掰曾,起點(diǎn)在左端旭蠕。
flex-direction: row-reverse; // 主軸為水平方向,起點(diǎn)在右端旷坦。
flex-direction: column; // 主軸為垂直方向掏熬,起點(diǎn)在上。
flex-direction: column-reverse; // 主軸為垂直方向秒梅,起點(diǎn)在下旗芬。
}
<span id="flex-wrap">flex-wrap 屬性</span>
flex-wrap
屬性決定子容器如果在一條軸線排不下時,如何換行捆蜀。
.ele {
flex-wrap: nowrap; // 默認(rèn)疮丛,不換行
flex-wrap: wrap; // 換行,第一行在上方辆它。
flex-wrap: wrap-reverse // 換行誊薄,第一行在下方。
justify-content 屬性
justify-content
屬性定義了子容器在主軸上的對齊方式锰茉。
.ele{
justify-content: flex-start; // 默認(rèn)呢蔫,左對齊
justify-content: flex-end; // 右對齊
justify-content: center; // 居中
justify-content: space-between; // 兩端對齊,項(xiàng)目之間的間隔都相等飒筑。
justify-content: space-around; // 每個項(xiàng)目兩側(cè)的間隔相等片吊。所以,項(xiàng)目之間的間隔比項(xiàng)目與邊框的間隔大一倍协屡。
}
```![justify-content 屬性](http://upload-images.jianshu.io/upload_images/4251036-84427c744d5bdaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#### flex-flow 屬性
`flex-flow` 屬性是 `flex-direction` 屬性和 `flex-wrap` 屬性的簡寫形式定鸟,默認(rèn)值為 `row nowrap`。
```css
.ele {
flex-flow: <flex-direction> || <flex-wrap>;
}
align-items 屬性
align-items
屬性定義自容器在交叉軸上如何對齊著瓶。
具體的對齊方式與交叉軸的方向有關(guān)联予,下面假設(shè)交叉軸從上到下。
.ele{
align-items: flex-start; // 交叉軸的起點(diǎn)對齊材原。
align-items: flex-end; // 交叉軸的終點(diǎn)對齊沸久。
align-items: center; // 交叉軸的中點(diǎn)對齊。
align-items: baseline; // 項(xiàng)目的第一行文字的基線對齊余蟹。
align-items: stretch; // 默認(rèn)卷胯,如果項(xiàng)目未設(shè)置高度或設(shè)為auto,將占滿整個容器的高度威酒。
}
align-content 屬性
align-content
屬性定義了多根軸線的對齊方式窑睁。如果項(xiàng)目只有一根軸線挺峡,該屬性不起作用。
.ele{
align-content: flex-start; // 與交叉軸的起點(diǎn)對齊
align-content; flex-end; // 與交叉軸的終點(diǎn)對齊担钮。
align-content: center; // 與交叉軸的中點(diǎn)對齊橱赠。
align-content: space-between;// 與交叉軸兩端對齊,軸線之間的間隔平均分布箫津。
align-content: space-around; // 每根軸線兩側(cè)的間隔都相等狭姨。所以,軸線之間的間隔比軸線與邊框的間隔大一倍苏遥。
align-content: stretch; // 默認(rèn) 軸線占滿整個交叉軸饼拍。
}
子容器屬性
子容器也有 6 個屬性:
- order:子容器的排列順序
- flex-grow:子容器剩余空間的拉伸比例
- flex-shrink:子容器超出空間的壓縮比例
- flex-basis:自容器在不伸縮情況下的原始尺寸
- flex:子元素的
flex
屬性是flex-grow
,flex-shrink
和flex-basis
的簡寫 - align-self
order 屬性
order
屬性定義項(xiàng)目的排列順序。數(shù)值越小田炭,排列越靠前师抄,默認(rèn)為 0。
.ele{
order: num;
}
flex-grow 屬性
flex-grow
屬性定義子容器的伸縮比例教硫。按照該比例給子容器分配空間叨吮。
.ele{
flex-grow: <number>; /* default 0 */
}
flex-shrink 屬性
flex-shrink
屬性定義了子容器彈性收縮的比例。如圖栋豫,超出的部分按 1:2 的比例從給子容器中減去挤安。此屬性要生效,父容器的 flex-wrap
屬性要設(shè)置為 nowrap
.ele{
flex-shrink: <number>; /* default 0 */
}
flex-basis 屬性
flex-basis
屬性定義了自容器在不伸縮情況下的原始尺寸丧鸯,主軸為橫向時代表寬度蛤铜,主軸為縱向時代表高度。
.ele{
flex-basis: <length> | auto; /* default auto */
}
flex 屬性
子元素的 flex
屬性是 flex-grow
,flex-shrink
和 flex-basis
的簡寫丛肢,默認(rèn)值為 0
1
auto
围肥。后兩個屬性可選。
該屬性有兩個快捷值:auto (1 1 auto) 和 none (0 0 auto)蜂怎。
align-self 屬性
子容器的 align-self
屬性允許單個項(xiàng)目有與其他項(xiàng)目不一樣的對齊方式穆刻,可覆蓋父容器 align-items
屬性。默認(rèn)值為 auto
杠步,表示繼承父元素的 align-items
屬性氢伟,如果沒有父元素,則等同于 stretch
幽歼。
.ele{
align-self: auto; // 繼承父元素的 align-items 屬性
align-self: flex-start; // 交叉軸的起點(diǎn)對齊朵锣。
align-self: flex-end; // 交叉軸的終點(diǎn)對齊。
align-self: center; // 交叉軸的中點(diǎn)對齊甸私。
align-self: baseline; // 項(xiàng)目的第一行文字的基線對齊诚些。
align-self: stretch; // 默認(rèn),如果項(xiàng)目未設(shè)置高度或設(shè)為auto皇型,將占滿整個容器的高度诬烹。
}
grid 網(wǎng)格布局
flex 布局雖然強(qiáng)大砸烦,但是只能是一維布局,如果要進(jìn)行二維布局绞吁,那么我們還需要使用 grid幢痘。
grid 布局又稱為“網(wǎng)格布局”,可以實(shí)現(xiàn)二維布局方式掀泳,和之前的 表格table
布局差不多雪隧,然而西轩,這是使用 CSS 控制的员舵,不是使用 HTML 控制的,同時還可以依賴于媒體查詢根據(jù)不同的上下文得新定義布局藕畔。
網(wǎng)格布局還可以讓我們擺脫現(xiàn)在布局中存在的文檔流限制马僻,換句話說,你的結(jié)構(gòu)不需要根據(jù)設(shè)計稿從上往上布置了注服。這也意味著您可以自由地更改頁面元素位置韭邓。這最適合你在不同的斷點(diǎn)位置實(shí)現(xiàn)你最需要的布局,而不再需要為響應(yīng)你的設(shè)計而擔(dān)心HTML結(jié)構(gòu)的問題溶弟。
和 table
布局不同的是女淑,grid
布局不需要在 HTML 中使用特定的標(biāo)簽布局,所有的布局都是在 CSS 中完成的辜御,你可以隨意定義你的 grid 網(wǎng)格鸭你。
沒有 HTML 結(jié)構(gòu)的網(wǎng)格布局有助于使用流體、調(diào)整順序等技術(shù)管理或更改布局擒权。通過結(jié)合 CSS 的媒體查詢屬性袱巨,可以控制網(wǎng)格布局容器和他們的子元素,使用頁面的布局根據(jù)不同的設(shè)備和可用空間調(diào)整元素的顯示風(fēng)格與定位碳抄,而不需要去改變文檔結(jié)構(gòu)的本質(zhì)內(nèi)容愉老。
瀏覽器兼容性如下:
grid 網(wǎng)格布局中的基本概念
此部分直接摘自CSS Grid布局:什么是網(wǎng)格布局
網(wǎng)格線(Grid Lines)
網(wǎng)格線組成了網(wǎng)格,他是網(wǎng)格的水平和垂直的分界線剖效。一個網(wǎng)格線存在行或列的兩側(cè)嫉入。我們可以引用它的數(shù)目或者定義的網(wǎng)格線名稱。
網(wǎng)格軌道(Grid Track)
網(wǎng)格軌道是就是相鄰兩條網(wǎng)格線之間的空間璧尸,就好比表格中行或列咒林。所在在網(wǎng)格中其分為grid column和grid row。每個網(wǎng)格軌道可以設(shè)置一個大小逗宁,用來控制寬度或高度映九。
網(wǎng)格單元格(Grid Cell)
網(wǎng)格單元格是指四條網(wǎng)格線之間的空間。所以它是最小的單位瞎颗,就像表格中的單元格件甥。
網(wǎng)格區(qū)域(Grid Area)
網(wǎng)格區(qū)域是由任意四條網(wǎng)格線組成的空間捌议,所以他可能包含一個或多個單元格。相當(dāng)于表格中的合并單元格之后的區(qū)域引有。
使用 grid 布局
使用 grid 布局很簡單瓣颅,通過display屬性設(shè)置屬性值為 grid 或 inline-grid 或者是 subgrid(該元素父元素為網(wǎng)格,繼承父元素的行和列的大衅┱) 就可以了宫补。
網(wǎng)格容器中的所有子元素就會自動變成網(wǎng)格項(xiàng)目(grid item),然后設(shè)置列(grid-template-columns)和 行(grid-template-rows)的大小,設(shè)置 grid-template-columns
有多少個參數(shù)生成的 grid 列表就有多少個列。
注:當(dāng)元素設(shè)置了網(wǎng)格布局凤瘦,column棒搜、float、clear、vertical-align屬性無效。
如果沒有設(shè)置 grid-template-columns
,那么默認(rèn)只有一列稚晚,寬度為父元素的 100%,例如
比如我們設(shè)置如下的 HTML型诚,
<div class="grid-container">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item4">4</div>
<div class="item item5">5</div>
<div class="item item6">6</div>
</div>
在 CSS 中客燕,我們不設(shè)置 grid-template-columns
,只設(shè)置 grid-template-row
.grid-container{
display: grid;
grid-template-rows: 50px 80px 100px;
background: pink;
}
.item{
border: 2px solid palegoldenrod;
color: #fff;
text-align: center;
font-size: 20px;
}
顯示如下
設(shè)置了 grid-template-columns
的話狰贯,設(shè)置了幾個參數(shù)也搓,就有幾列(不超過 grid item 的個數(shù)),然后設(shè)置的 grid-template-row
參數(shù)就是每一列的高度(超出列數(shù)的高度無效)
比如:
.grid-container{
padding: 20px;
display: grid;
grid-template-rows: 50px 100px 60px 80px;
grid-template-columns: 50px 40px 100px 80px;
background: pink;
}
.item{
border: 2px solid palegoldenrod;
color: #fff;
}
雖然我們設(shè)置了四個 grid-template-rows
暮现,但是因?yàn)橹挥袃尚谢够妫灾挥星皟蓚€值生效。效果如下:
當(dāng)然栖袋,我們也可以像 flex 一樣設(shè)置每一列的寬度:
.grid-container{
padding: 20px;
display: grid;
grid-template-rows: 50px 100px 60px;
grid-template-columns: 1fr 1fr 2fr;
background: pink;
}
注意到我們使用了一個新的單位:fr
css fr 單位是一個自適應(yīng)單位拍顷,fr單位被用于在一系列長度值中分配剩余空間,如果多個已指定了多個部分塘幅,則剩下的空間根據(jù)各自的數(shù)字按比例分配昔案。
tips:fr 是基于網(wǎng)格容器可用空間來計算的(flex 也是一樣),所以我們可以和其他單位混合使用电媳,如果需要的話
是不是找到了 flex 的感覺踏揣,這樣設(shè)置效果如下:
行或列最小和最大尺寸
minmax()
函數(shù)來創(chuàng)建行或列的最小或最大尺寸,第一個參數(shù)定義網(wǎng)格軌道的最小值匾乓,第二個參數(shù)定義網(wǎng)格軌道的最大值捞稿。可以接受任何長度值,也接受 auto
值娱局。auto
值允許網(wǎng)格軌道基于內(nèi)容的尺寸拉伸或擠壓彰亥。
.grid-container{
padding: 20px;
display: grid;
grid-template-rows: minmax(100px,200px) minmax(50px,200px);
grid-template-columns: 1fr 1fr 2fr;
background: pink;
height: 300px;
}
我們將第一行的高度設(shè)置為 minmax(100px,200px)
,第二行的高度設(shè)置為minmax(50px,200px)
衰齐,容器總高度設(shè)置為 300px
任斋,這時每一列的高度要怎么算呢?
先判斷總高度是小于第一列高度的最大值和第二列高度的最大值之和的耻涛,如果大于最大值之和废酷,那么第一列和第二列的高度都為設(shè)置的最大值,如果是小于最小值之和的話抹缕,那么第一列和第二列的高度都為設(shè)置的最小值澈蟆。
現(xiàn)在問題來了,我們這種情況是總高度是小于第一列高度的最大值和第二列高度的最大值之和的歉嗓,這樣就是先用 總高度 300px
- 第一列最小高度 100px
- 第二列最小高度 50px
= 150px
丰介。
第一列高度:第一列最小高度 100px
+ 150px/2
= 175px
;
第二列高度:第一列最小高度 50px
+ 150px/2
= 125px
;
效果如下:
重復(fù)行或者列
repeat()
屬性可以創(chuàng)建重復(fù)的網(wǎng)格軌道背蟆。這個適用于創(chuàng)建相等尺寸的網(wǎng)格項(xiàng)目和多個網(wǎng)格項(xiàng)目鉴分。
repeat()
也接受兩個參數(shù):第一個參數(shù)定義網(wǎng)格軌道應(yīng)該重復(fù)的次數(shù),第二個參數(shù)定義每個軌道的尺寸带膀。
.grid-container{
padding: 20px;
display: grid;
grid-template-columns: repeat(2,100px);
grid-template-rows: repeat(3,100px);
background: pink;
}
效果如下:
間距
grid-column-gap
:創(chuàng)建列與列之間的距離志珍。
grid-row-gap
:行與行之間的距離。
.grid-container{
padding: 20px;
display: grid;
grid-template-columns: repeat(2,100px);
grid-template-rows: repeat(3,100px);
grid-column-gap: 50px;
grid-row-gap: 15px;
background: pink;
}
或者使用 grid-gap
是 grid-row-gap
和 grid-column-gap
兩個屬性的縮寫垛叨。
通過網(wǎng)格線定位 grid item
我們可以通過表格線行或者列來定位 grid item伦糯。比如:
<div class="grid-container">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item4">4</div>
<div class="item item5">5</div>
<div class="item item6">6</div>
</div>
.grid-container{
padding: 20px;
display: grid;
grid-template-columns: repeat(2,100px);
grid-template-rows: repeat(3,100px);
grid-column-gap: 50px;
grid-row-gap: 15px;
background: pink;
}
.item{
border: 2px solid palegoldenrod;
color: #fff;
text-align: center;
font-size: 20px;
}
.item1{
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: 2;
grid-column-end: 3;
background: #fffa90;
color: #000;
}
效果:
grid-row
是 grid-row-start
和 grid-row-end
的簡寫。grid-column
是 grid-column-start
和 grid-column-end
的簡寫嗽元。
如果只提供一個值敛纲,指定了 grid-row-start
和 grid-column-start
的值。
如果提供兩個值剂癌,第一個值是 grid-row-start
或者 grid-column-start
的值淤翔,第二個值是 grid-row-end
或者 grid-column-end
的值,兩者之間必須要用/隔開佩谷。
grid-row: 2;
grid-column: 3 / 4;
這四個值可以用 grid-area
縮寫旁壮,分別對應(yīng) grid-row-start
、grid-column-start
谐檀、grid-row-end
抡谐、grid-column-end
:
grid-area: 2 / 2 / 3 / 3;
合并單元行與合并單元列
這個就和 excel 中的合并單元行/列是相同的(這個需要設(shè)置在 grid item 中),
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 2;
grid-row-end: 4;
grid-row-end: 4;
也可以使用 grid-row
和 grid-column
簡寫的形式桐猬,關(guān)鍵詞 span
后面緊隨數(shù)字麦撵,表示合并多少個列或行,/
前面是從第幾行/列開始。
grid-row: 2 / span 3;
grid-column: span 2;
.grid-container{
padding: 20px;
display: grid;
grid-template-columns: repeat(4,100px);
grid-template-rows: repeat(3,100px);
grid-column-gap: 50px;
grid-row-gap: 15px;
background: pink;
}
.item{
border: 2px solid palegoldenrod;
color: #fff;
text-align: center;
font-size: 20px;
}
.item1{
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 2;
grid-row-end: 4;
}
效果如圖:
自定義網(wǎng)格線名稱
在 grid 中免胃,是可以自定義網(wǎng)格線的名稱的五垮,然后使用定義好的網(wǎng)格線來進(jìn)行布局,[col1-start]
網(wǎng)格線名稱一定要使用 []
括住杜秸。
<div class="grid-container">
<div class="item a">a</div>
<div class="item b">b</div>
<div class="item c">c</div>
<div class="item d">d</div>
<div class="item e">e</div>
<div class="item f">f</div>
<div class="item g">g</div>
<div class="item h">h</div>
<div class="item i">i</div>
<div class="item j">j</div>
</div>
.grid-container{
text-align: center;
height: 400px;
padding: 100px;
display: grid;
grid-column-gap: 5px;
grid-row-gap: 5px;
background: pink;
grid-template-columns: [col1-start] 100px [col1-end] 5px [col2-start] 100px [col2-end] 5px [col3-start]
100px [col3-end] 5px [col4-start] 100px [col4-end];
grid-template-rows: [row1-start] auto [row1-end] 5px [row2-start] auto [row2-end] 5px [row3-start] auto
[row3-end] 5px [row4-start] auto [row4-end] 5px [row5-start] auto [row5-end];
}
.a { grid-column: col1-start / col3-end; grid-row: row1-start;
background: #ffffff;}
.b { grid-column: col4-start / col4-end; grid-row: row1-start / row5-end; background: orange; }
.c { grid-column: col1-start; grid-row: row2-start; background: #ffffff;}
.d { grid-column: col2-start; grid-row: row2-start; background: #ffffff;}
.e { grid-column: col3-start; grid-row: row2-start; background: #ffffff;}
.f { grid-column: col1-start / col2-end; grid-row: row3-start; background: #ffffff;}
.g { grid-column: col3-start; grid-row: row3-start; background: #ffffff;}
.h { grid-column: col1-start; grid-row: row4-start; background: #ffffff;}
.i { grid-column: col2-start / col3-end; grid-row: row4-start; background: #ffffff;}
.j { grid-column: col1-start / col3-end; grid-row: row5-start; background: #ffffff;}
最后的顯示效果是這樣的(文字和輔助線是后臺添加的):
通過網(wǎng)格區(qū)域命名和定位網(wǎng)格項(xiàng)目
什么是網(wǎng)格區(qū)域:
網(wǎng)格區(qū)域(grid-area)是一個邏輯空間放仗,主要用來放置一個或多個網(wǎng)格單元格(Grid Cell)。他是由四條網(wǎng)格線(Grid line)撬碟,網(wǎng)格區(qū)域每邊一條诞挨,四邊相交組織的網(wǎng)格軌道(Grid Track)。簡單點(diǎn)理解呢蛤,網(wǎng)格區(qū)域是有四條網(wǎng)格線交織組成的網(wǎng)格空間惶傻,這個空間中可能是一個網(wǎng)格單元格,也可能是多個網(wǎng)格單元格其障。
定義網(wǎng)格區(qū)域
在CSS Grid Layout中定義網(wǎng)格區(qū)域有兩種方式银室,一種是通過網(wǎng)格線來定義,另一種是通過grid-template-areas來定義励翼。接下來看看兩種定義網(wǎng)格區(qū)域的方法在具體使用過程中有何不同蜈敢。
網(wǎng)格線定義網(wǎng)格區(qū)域
使用網(wǎng)格線定義網(wǎng)格區(qū)域的方法非常的簡單,首先依賴于 grid-template-columns
和 grid-template-rows
顯式定義網(wǎng)格線汽抚,甚至是由瀏覽器隱式創(chuàng)建網(wǎng)格線抓狭,然后通過 grid-area
屬性通過取網(wǎng)格線,組成網(wǎng)格線交織區(qū)域造烁,那么這個區(qū)域就是所講的網(wǎng)格區(qū)域否过。在使用 grid-area
屬性調(diào)用網(wǎng)格線,其遵循的規(guī)則是 grid-area: row-start
/ column-start
/ row-end
/ column-end
惭蟋。
grid-template-areas
定義網(wǎng)格區(qū)域
除了使用網(wǎng)格線的交組來定義網(wǎng)格區(qū)域之外苗桂,在 CSS Grid Layout 中還可以通過 grid-template-areas
屬性來定義網(wǎng)格區(qū)域的名稱,然后需要放在對應(yīng)網(wǎng)格區(qū)域的元素告组,可以通過 grid-area
屬性來指定煤伟。而且重復(fù)區(qū)域可以使用同一個名稱來實(shí)現(xiàn)跨區(qū)域。另外對于空的軌道區(qū)域惹谐,可以使用點(diǎn)號 .
來代表
<div class="grid-container">
<div class="header ">header</div>
<div class="content ">content</div>
<div class="sidebar ">sidebar</div>
<div class="footer ">footer</div>
</div>
.grid-container{
text-align: center;
padding: 20px;
display: grid;
grid-column-gap: 5px;
grid-row-gap: 5px;
background: pink;
grid-template-areas: "header header header header header"
"sidebar content content content content"
"footer footer footer footer footer";
grid-template-rows: 50px 150px 50px;
grid-template-columns: 200px 200px 200px;
}
.header { grid-area:header; background: #fff}
.content { grid-area: content; background: #fffa90}
.sidebar { grid-area: sidebar; background: #5bc0de}
.footer { grid-area: footer; background: #ffff00}
我發(fā)現(xiàn)這樣布局的一個優(yōu)點(diǎn)持偏,在不設(shè)置高度的情況下(父容器和 grid-template-rows
的值,或者 grid-template-rows
設(shè)置為 auto
時氨肌,slider
和 content
的高度是一致的鸿秆,并且會根據(jù)其內(nèi)的高度自適應(yīng))
例如:
常用的 CSS 布局
在介紹了 CSS 的布局方式之后,我們來看一下常用的 CSS 布局有哪些
水平垂直居中(感覺總結(jié)的并不是很好)
感覺垂直居中真的是已經(jīng)被講爛了怎囚,但是在平時做項(xiàng)目時卿叽,我都是靠試的桥胞,導(dǎo)致面試的時候被問到有時候回答不上來,現(xiàn)在就用自己的方式來總結(jié)一下考婴。其實(shí)這個方式是有很多的贩虾,但就是看的教程太多了,導(dǎo)致最后一個都沒有記住沥阱,所以我決定盡可能的將情況考慮完整缎罢,然后每一種情況只記住一個最佳實(shí)踐。
對于居中考杉,我個人認(rèn)為不需要背什么“x 種方式實(shí)現(xiàn) xx”這樣的例子策精,我們只需要了解其原理即可寫出符合要求的 css。
水平崇棠、垂直居中咽袜,個人比較喜歡用絕對定位的方法實(shí)現(xiàn),其次就是使用 table
布局枕稀,因?yàn)樽詭Т怪本又醒病H绻菃涡械男袃?nèi)元素使用 line-height
等于 height
,對于多行元素的垂直居中萎坷,大部分都是使用 table
元素(求推薦更好的布局)凹联,當(dāng)然還有 flex 和 grid 布局。
水平居中
一般水平居中還是比較容易的食铐,我一般都是先看子元素是固定寬度還是寬度未知
固定寬度
這種方式是絕對定位居中匕垫,除了使用 margin
,我們還可以使用 transform
(注意瀏覽器兼容性虐呻,只適用于 ie9+,移動開發(fā)請忽略)
.container{
width: 300px;
height: 200px;
background: pink;
position: relative;
}
.inner{
width: 100px;
height: 50px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -25px;
margin-left: -50px;
background: #fff;
text-align: center;
}
.container{
width: 300px;
height: 200px;
background: pink;
position: relative;
}
.inner{
width: 100px;
height: 50px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #fff;
text-align: center;
}
或者使用 magin:0 auto
寞秃;但一般情況下我都會使用上一種斟叼,因?yàn)榱?xí)慣了(?_?)
寬度未知
將子元素設(shè)置為行內(nèi)元素,然后父元素設(shè)置 text-align: center
春寿。
.container{
width: 300px;
height: 200px;
background: pink;
position: relative;
text-align: center;
}
.inner{
display: inline-block;
}
多個塊狀元素
上面的方式即使子元素不止一個也想實(shí)現(xiàn)水平居中也是有效的朗涩,(寬度固定不固定都可,不固定的話就不需要設(shè)置寬度绑改,會被自動撐開谢床,但是要考慮到撐爆的情況)例如:
.container{
width: 250px;
height: 200px;
background: pink;
position: relative;
text-align: center;
padding: 20px;
}
.inner{
display: inline-block;
width: 50px;
height: 150px;
margin: 0 auto;
background: #fff;
text-align: center;
}
當(dāng)然也可以使用我們剛剛介紹的 flex,我們只需要讓子元素在主軸上的對齊方式設(shè)置為居中就可以
.container{
width: 250px;
height: 200px;
background: pink;
display: flex;
justify-content: center;
padding: 20px;
}
.inner{
background: #fff;
width: 50px;
height: 150px;
margin-left: 10px;
}
垂直居中
單行行內(nèi)元素
單行海內(nèi)元素居中厘线,只需要將子元素的行高等于高度就可以了识腿。
#container {
height: 400px;
background: pink;
}
#inner{
display: inline-block;
height: 200px;
line-height: 200px;
}
多行元素
上面的這種方式只能處理單行的行內(nèi)元素,對于多行的行內(nèi)元素是處理不了的造壮,因?yàn)榻o每一個子元素都設(shè)置了 line-height
渡讼,看了很多方法,要不是沒有效果,要不然就是又局限性成箫,提到最多的是使用 table-cell
的方式(但是貌似這個方法也有一點(diǎn)弊端展箱,那就是其子元素的表現(xiàn)形式和行內(nèi)元素類似,子元素不能獨(dú)占一行)蹬昌,當(dāng)然如果你有更好的方式混驰,歡迎提出:
.container {
width: 200px;
height: 400px;
background: pink;
position: absolute;
display: table;
vertical-align:middle;
}
.inner{
display: table-cell;
vertical-align:middle;
}
還有一個方法是設(shè)置一個空的行內(nèi)元素,使其 height:100%
皂贩,display:inline-block
,vertical-align: middle;
并且 font-size:0
账胧。但是這樣方式的原理我還不是很清楚,只是知道要設(shè)置一個空元素先紫,高度和父元素相等治泥,并且設(shè)置垂直居中的屬性。但是遮精,這只是用與所有的行內(nèi)元素的寬度和不超過父元素的寬度的情況居夹。
<div class="container">
![](WechatIMG110.jpg)
![](WechatIMG110.jpg)
![](WechatIMG110.jpg)
<p>123</p>
</div>
.container{
width: 400px;
height: 100px;
background: pink;
text-align: center;
}
img{
vertical-align: middle;
}
p{
display: inline-block;
height: 100%;
line-height: 100%;
vertical-align: middle;
font-size: 0;
}
效果:
另一個一勞永逸的方法就是 flex,但是要注意瀏覽器的兼容性本冲。
圖片和文字垂直居中
經(jīng)常有看到設(shè)計稿是圖片和文字垂直居中的准脂,那么怎么才能讓圖片和文字垂直居中呢?
只需要給圖片一個 vertical-align: middle;
屬性就可以:
<div class="container">
![](WechatIMG110.jpg)
<p>123456</p>
</div>
.container {
background: pink;
padding: 20px;
height: 400px;
}
.container img{
display: inline-block;
vertical-align: middle;
}
.container p{
display: inline-block;
}
效果如下:
重點(diǎn)來啦~
自我感覺總結(jié)的居中問題不是特別的好檬洞,我們現(xiàn)在可以來總結(jié)一下其中的原理:
- 我們要實(shí)現(xiàn)水平或者垂直居中狸膏,應(yīng)該從兩方面下手:元素自帶居中的效果或者強(qiáng)制讓其顯示在中間。
- 所以我們先考慮添怔,哪些元素有自帶的居中效果湾戳,最先想到的應(yīng)該就是
text-align:center
了,但是這個只對行內(nèi)元素有效广料,所以我們要使用text-align:center
就必須將子元素設(shè)置為display: inline;
或者display: inline-block;
砾脑; - 接下來我們可能會想既然有
text-align
那么會不會對應(yīng)也有自帶垂直居中的呢,答案是有的vertical-align:
艾杏,我一直不是很喜歡使用這個屬性韧衣,因?yàn)槭斡茫?.9 次都沒有垂直居中,一度讓我懷疑人生」荷#現(xiàn)在貌似也搞得不是很清楚畅铭,看了 張鑫旭的文章 居然看得也不是很懂,笑哭勃蜘。目前就在table
中設(shè)置有效硕噩,因?yàn)?table
元素 的特性,打娘胎里面帶的就是好用元旬。還有一種可以有效的方式是前面提到的空元素的方式榴徐,不過感覺多設(shè)置一個元素還不如使用table
守问。 - 還有一只設(shè)置垂直居中的是將行內(nèi)元素的
line-height
和height
設(shè)置為相同(只適用于單行行內(nèi)元素) - 固定寬度或者固定高度的情況個人認(rèn)為設(shè)置水平垂直居最簡單,可以直接使用絕對定位坑资。使用絕對定位就是子元素相對于父元素的位置耗帕,所以將父元素設(shè)置
position:reletive
對應(yīng)的子元素要設(shè)置position:absolute
,然后使用top:50%;left:50%
袱贮,將子元素的左上角和父元素的中點(diǎn)對齊仿便,之后再設(shè)置偏移margin-top: 1/2 子元素高度;margin-left: 1/2 子元素寬度;
。這種方式也很好理解攒巍。 - 上面的絕對定位方法只要將
margin
改為transform
就可以實(shí)現(xiàn)寬度和高度未知的居中(兼容性啊兄弟們嗽仪!(?_?))transformX:50%;transformY:50%
;
不行柒莉,感覺總結(jié)的還是很渣闻坚,╮(╯▽╰)╭哎,誰有好的方法兢孝,求推薦窿凤。
圣杯布局
其實(shí)我還真是第一次聽說圣杯布局這種稱呼,看了下這個名字的由來跨蟹,貌似和布局并沒有什么關(guān)系雳殊,圣杯布局倒是挺常見的三欄式布局。兩邊頂寬窗轩,中間自適應(yīng)的三欄布局夯秃。
效果如下:
這個布局方式的關(guān)鍵是怎么樣才能使得在伸縮瀏覽器窗口的時候讓中間的子元素寬度改變×∫眨可以適應(yīng)瀏覽器的寬度變化使用百分比設(shè)置寬度再合適不過仓洼,所以我們要將中間子元素的寬度設(shè)置為 100%
,左邊和右邊的子元素設(shè)置為固定的寬度腹备。
我們就來實(shí)現(xiàn)一下這樣的布局:
給出HTML結(jié)構(gòu)
HTML 文件就很普通:
<div class="container">
<div class="middle">測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
這里我們要注意的是衬潦,中間欄要在放在文檔流前面以優(yōu)先渲染。
給出每個子元素的樣式
然后我們寫 CSS植酥,我們現(xiàn)將其三個元素的寬度和高度設(shè)置好,然后都設(shè)置為 float:left
:
.middle{
width: 100%;
background: paleturquoise;
height: 200px;
float: left;
}
.left{
background: palevioletred;
width: 200px;
height: 200px;
float: left;
font-size: 40px;
color: #fff;
}
.right{
width: 200px;
height: 200px;
background: purple;
font-size: 40px;
float: left;
color: #fff;
}
這時的效果如下:
使子元素在同一行顯示
我們可以看出弦牡,現(xiàn)在三個子元素是在一排顯示的友驮,因?yàn)槲覀兘o中間的子元素設(shè)置的寬度是 100%
,并且中間的子元素在文檔流的最前面驾锰,最先被渲染卸留。
那么我們要使得三個元素在同一排顯示。接下來我們要將 .left
和 .right
向上提椭豫。實(shí)際上我們是使用 margin-left
為 負(fù)值來實(shí)現(xiàn)的耻瑟,我們將 .left
的 margin-left
設(shè)置為 -100%
(負(fù)的中間子元素的寬度)旨指,這樣,左邊的元素就會被“提升”到上一層喳整。
然后就是右邊子元素了谆构,只需要設(shè)置 margin-left
設(shè)置為負(fù)的自身的寬度。
結(jié)果如下:
使得中間子元素不被遮蓋
從上一張截圖顯示中顯示中間的子元素被遮擋了框都,所以說我們要解決這個問題搬素,要怎么解決呢?嗯... 只要使得中間的子元素顯示的寬度剛好為左邊元素和右邊元素顯示中間的寬度就可以魏保。同時我們還必須保證是使用的半分比的布局方式熬尺。
這樣的話有一種方式可以即使中間的寬度減少,又可以使中間的寬度仍然使用 100%
谓罗,那就是設(shè)置父元素的 padding
值粱哼,將父元素的 padding-left
設(shè)置為左邊子元素的寬度,將父元素的 padding-right
設(shè)置為右邊子元素的寬度檩咱。
顯示效果如下:
將左邊和右邊的子元素像兩邊移動
嗯... 這貌似也不是我們想要的效果揭措,但是,中間的子元素確實(shí)是在中間了税手,那么我們只需要設(shè)置相對位置蜂筹,將左邊的子元素和右邊的子元素向兩邊移動就好。
最終的 CSS 代碼如下:
.container{
padding: 0 200px;
}
.middle{
width: 100%;
background: paleturquoise;
height: 200px;
float: left;
}
.left{
background: palevioletred;
width: 200px;
height: 200px;
float: left;
font-size: 40px;
color: #fff;
margin-left:-100%;
}
.right{
width: 200px;
height: 200px;
background: purple;
font-size: 40px;
float: left;
color: #fff;
margin-left:-200px;
}
最終效果如下:
雙飛翼布局
其實(shí)雙飛翼布局是為了解決圣杯布局的弊端提出的芦倒,如果你跟我一起將上面的圣杯布局的代碼敲了一遍艺挪,你就會發(fā)現(xiàn)一個問題,當(dāng)你將瀏覽器寬度縮短到一定程度的時候兵扬,會使得中間子元素的寬度比左右子元素寬度小的時候麻裳,這時候布局就會出現(xiàn)問題。所以首先器钟,這提示了我們在使用圣杯布局的時候一定要設(shè)置整個容器的最小寬度津坑。
雙飛翼和圣杯布局區(qū)別
圣杯布局和雙飛翼布局解決問題的方案在前一半是相同的,也就是三欄全部float浮動傲霸,但左右兩欄加上負(fù)margin讓其跟中間欄div并排疆瑰,以形成三欄布局。
不同在于解決”中間欄div內(nèi)容不被遮擋“問題的思路不一樣:圣杯布局昙啄,為了中間div內(nèi)容不被遮擋穆役,將中間div設(shè)置了左右padding-left和padding-right后,將左右兩個div用相對布局position: relative并分別配合right和left屬性梳凛,以便左右兩欄div移動后不遮擋中間div耿币。
雙飛翼布局,為了中間div內(nèi)容不被遮擋韧拒,直接在中間div內(nèi)部創(chuàng)建子div用于放置內(nèi)容淹接,在該子div里用margin-left和margin-right為左右兩欄div留出位置十性。
作者:知乎用戶
鏈接:https://www.zhihu.com/question/21504052/answer/50053054
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)塑悼,非商業(yè)轉(zhuǎn)載請注明出處劲适。
所以只是一個小小的改動
<div class="container">
<div class="middle-container">
<div class="middle">測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試</div>
</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
.middle-container{
width: 100%;
background: paleturquoise;
height: 200px;
float: left;
}
.middle{
margin-left: 200px;
margin-right: 200px;
}
.left{
background: palevioletred;
width: 200px;
height: 200px;
float: left;
font-size: 40px;
color: #fff;
margin-left:-100%;
}
.right{
width: 200px;
height: 200px;
background: purple;
font-size: 40px;
float: left;
color: #fff;
margin-left:-200px;
}
這樣,在我們將中間元素寬度調(diào)到比兩邊元素小的時候拢肆,也是可以正常顯示减响,但是如果總寬度小于左邊元素或者右邊元素的時候,還是會有問題郭怪。
提問
如果你已經(jīng)看到了這里支示,那么很感謝,已經(jīng)到最后了鄙才,我承認(rèn)颂鸿,這篇文章真的很長...
所以,來攒庵,打起精神嘴纺,對于下面的布局方式,大家都什么好的布局方式或者奇淫技巧呢~
其實(shí)我只是想知道左邊頭像和下面的文字垂直居中有什么好的方法浓冒。
此問題可以簡化為栽渴,多個未知高度的元素如何垂直居中?對了稳懒,不使用 flex 和grid 布局闲擦,要求兼容 ie8+。
大家捧個場场梆,可以直接發(fā)郵件將你的代碼發(fā)給我墅冷,我郵件地址:991939332@qq.com,謝謝大家或油,謝謝謝謝