本文首發於個人我的網站:cherryblog.sitecss
舒適提示:本文較長,圖片較多,原本是想寫一篇 CSS 佈局方式的,可是奈何 CSS 佈局方式種類太多而且實現方法太多,因此本文主要是介紹 flex 佈局和 grid 佈局,以及 CSS 常見的居中方式和兩種經典的佈局方式「聖盃佈局」和「雙飛翼佈局」。想到哪寫到哪,請各位見諒。html
咱們的傳統佈局方式就是經過盒模型,使用 display
屬性(文檔流佈局) + position
屬性(定位佈局) + float
屬性(浮動佈局)。這個你們都比較熟悉,沒有掌握的同窗再去惡補一下基礎css3
這是最基本的佈局方式,就是按照文檔的順序一個一個顯示出來,塊元素獨佔一行,行內元素共享一行,這個相信你們都比較熟悉了,就再也不贅述了web
浮動方式佈局就是使用 float
屬性,使元素脫離文檔流,浮動起來。這個你們也比較熟悉,就再也不贅述了。面試
咱們也能夠經過 position
屬性來進行定位,這個你們也比較熟悉了,就再也不贅述了。瀏覽器
2009年,W3C 提出了一種新的方案----Flex 佈局,能夠簡便、完整、響應式地實現各類頁面佈局。目前,它已經獲得了全部瀏覽器的支持,這意味着,如今就能很安全地使用這項功能。安全
Flex 是 Flexible Box 的縮寫,意爲"彈性佈局",用來爲盒狀模型提供最大的靈活性。bash
flex 是一種新型的佈局方式,使用該佈局方式能夠實現幾乎全部你想要的效果。可是要注意其瀏覽器的兼容性,flex 只支持 ie 10+,全部仍是要根據你的項目狀況使用(沒錯,咱們要求至少 ie 9,(ಥ_ಥ))。
ide
flex 的使用方法很簡單,只須要將其 display
屬性設置爲 flex
就能夠,也能夠設置行內的 flex,記得 Webkit 內核的瀏覽器,必須加上 -webkit
前綴。注意,設爲 Flex 佈局之後,子元素的 float
、clear
和 vertical-align
屬性將失效。wordpress
.ele{
display: -webkit-flex;
display: flex;
display: inline-flex;
display: -webkit-inline-flex;
}複製代碼
在 flex 中,最核心的概念就是容器和軸,全部的屬性都是圍繞容器和軸設置的。其中,容器分爲父容器和子容器。軸分爲主軸和交叉軸(主軸默認爲水平方向,方向向右,交叉軸爲主軸順時針旋轉 90°)。
在使用 flex 的元素中,默認存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)
主軸開始的位置稱爲 main start
,主軸結束的位置稱爲 main end
。
同理,交叉軸開始的位置稱爲 cross start
,交叉軸結束的位置稱爲 cross end
。
在使用 flex 的子元素中,佔據的主軸空間叫作 main size
,佔據的交叉軸空間叫作 cross size
。
父容器上有六個屬性
flex-direction
屬性和 flex-wrap
屬性的簡寫形式。flex-direction 屬性決定主軸的方向(主軸的方向不必定是水平的,這個屬性就是設置主軸的方向,主軸默認是水平方向,從左至右,若是主軸方向設置完畢,那麼交叉軸就不須要設置,交叉軸永遠是主軸順時針旋轉 90°)。
.ele {
flex-direction: row; // 默認值,主軸爲水平方向,起點在左端。
flex-direction: row-reverse; // 主軸爲水平方向,起點在右端。
flex-direction: column; // 主軸爲垂直方向,起點在上。
flex-direction: column-reverse; // 主軸爲垂直方向,起點在下。
}複製代碼
flex-wrap
屬性決定子容器若是在一條軸線排不下時,如何換行。
.ele {
flex-wrap: nowrap; // 默認,不換行
flex-wrap: wrap; // 換行,第一行在上方。
flex-wrap: wrap-reverse // 換行,第一行在下方。複製代碼
justify-content
屬性定義了子容器在主軸上的對齊方式。
.ele{
justify-content: flex-start; // 默認,左對齊
justify-content: flex-end; // 右對齊
justify-content: center; // 居中
justify-content: space-between; // 兩端對齊,項目之間的間隔都相等。
justify-content: space-around; // 每一個項目兩側的間隔相等。因此,項目之間的間隔比項目與邊框的間隔大一倍。
}複製代碼
flex-flow
屬性是 flex-direction
屬性和 flex-wrap
屬性的簡寫形式,默認值爲 row nowrap
。
.ele {
flex-flow: <flex-direction> || <flex-wrap>;
}複製代碼
align-items
屬性定義子容器在交叉軸上如何對齊。
具體的對齊方式與交叉軸的方向有關,下面假設交叉軸從上到下。
.ele{
align-items: flex-start; // 交叉軸的起點對齊。
align-items: flex-end; // 交叉軸的終點對齊。
align-items: center; // 交叉軸的中點對齊。
align-items: baseline; // 項目的第一行文字的基線對齊。
align-items: stretch; // 默認,若是項目未設置高度或設爲auto,將佔滿整個容器的高度。
}複製代碼
align-content
屬性定義了多根軸線的對齊方式。若是項目只有一根軸線,該屬性不起做用。
.ele{
align-content: flex-start; // 與交叉軸的起點對齊
align-content; flex-end; // 與交叉軸的終點對齊。
align-content: center; // 與交叉軸的中點對齊。
align-content: space-between;// 與交叉軸兩端對齊,軸線之間的間隔平均分佈。
align-content: space-around; // 每根軸線兩側的間隔都相等。因此,軸線之間的間隔比軸線與邊框的間隔大一倍。
align-content: stretch; // 默認 軸線佔滿整個交叉軸。
}複製代碼
子容器也有 6 個屬性:
flex
屬性是 flex-grow
,flex-shrink
和 flex-basis
的簡寫order
屬性定義項目的排列順序。數值越小,排列越靠前,默認爲 0。
.ele{
order: num;
}複製代碼
flex-grow
屬性定義子容器的伸縮比例。按照該比例給子容器分配空間。
.ele{
flex-grow: <number>; /* default 0 */
}複製代碼
flex-shrink
屬性定義了子容器彈性收縮的比例。如圖,超出的部分按 1:2 的比例從給子容器中減去。此屬性要生效,父容器的 flex-wrap
屬性要設置爲 nowrap
.ele{
flex-shrink: <number>; /* default 0 */
}複製代碼
flex-basis
屬性定義了子容器在不伸縮狀況下的原始尺寸,主軸爲橫向時表明寬度,主軸爲縱向時表明高度。
.ele{
flex-basis: <length> | auto; /* default auto */
}複製代碼
子元素的 flex
屬性是 flex-grow
,flex-shrink
和 flex-basis
的簡寫,默認值爲 0
1
auto
。後兩個屬性可選。
該屬性有兩個快捷值:auto (1 1 auto) 和 none (0 0 auto)。
子容器的 align-self
屬性容許單個項目有與其餘項目不同的對齊方式,可覆蓋父容器 align-items
屬性。默認值爲 auto
,表示繼承父元素的 align-items
屬性,若是沒有父元素,則等同於 stretch
。
.ele{
align-self: auto; // 繼承父元素的 align-items 屬性
align-self: flex-start; // 交叉軸的起點對齊。
align-self: flex-end; // 交叉軸的終點對齊。
align-self: center; // 交叉軸的中點對齊。
align-self: baseline; // 項目的第一行文字的基線對齊。
align-self: stretch; // 默認,若是項目未設置高度或設爲auto,將佔滿整個容器的高度。
}複製代碼
flex 佈局雖然強大,可是隻能是一維佈局,若是要進行二維佈局,那麼咱們還須要使用 grid。
grid 佈局又稱爲「網格佈局」,能夠實現二維佈局方式,和以前的 表格table
佈局差很少,然而,這是使用 CSS 控制的,不是使用 HTML 控制的,同時還能夠依賴於媒體查詢根據不一樣的上下文得新定義佈局。
網格佈局還可讓咱們擺脫如今佈局中存在的文檔流限制,換句話說,你的結構不須要根據設計稿從上往上佈置了。這也意味着您能夠自由地更改頁面元素位置。這最適合你在不一樣的斷點位置實現你最須要的佈局,而再也不須要爲響應你的設計而擔憂HTML結構的問題。
和 table
佈局不一樣的是,grid
佈局不須要在 HTML 中使用特定的標籤佈局,全部的佈局都是在 CSS 中完成的,你能夠隨意定義你的 grid 網格。
沒有 HTML 結構的網格佈局有助於使用流體、調整順序等技術管理或更改佈局。經過結合 CSS 的媒體查詢屬性,能夠控制網格佈局容器和他們的子元素,使用頁面的佈局根據不一樣的設備和可用空間調整元素的顯示風格與定位,而不須要去改變文檔結構的本質內容。
此部分直接摘自CSS Grid佈局:什麼是網格佈局
網格線組成了網格,他是網格的水平和垂直的分界線。一個網格線存在行或列的兩側。咱們能夠引用它的數目或者定義的網格線名稱。
網格軌道是就是相鄰兩條網格線之間的空間,就比如表格中行或列。所在在網格中其分爲grid column和grid row。每一個網格軌道能夠設置一個大小,用來控制寬度或高度。
網格單元格是指四條網格線之間的空間。因此它是最小的單位,就像表格中的單元格。
網格區域是由任意四條網格線組成的空間,因此他可能包含一個或多個單元格。至關於表格中的合併單元格以後的區域。
使用 grid 佈局很簡單,經過display屬性設置屬性值爲 grid 或 inline-grid 或者是 subgrid(該元素父元素爲網格,繼承父元素的行和列的大小) 就能夠了。
網格容器中的全部子元素就會自動變成網格項目(grid item),而後設置列(grid-template-columns)和 行(grid-template-rows)的大小,設置 grid-template-columns
有多少個參數生成的 grid 列表就有多少個列。
注:當元素設置了網格佈局,column、float、clear、vertical-align屬性無效。
若是沒有設置 grid-template-columns
,那麼默認只有一列,寬度爲父元素的 100%,例如
好比咱們設置以下的 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 中,咱們不設置 grid-template-columns
,只設置 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;
}複製代碼
顯示以下
設置了 grid-template-columns
的話,設置了幾個參數,就有幾列(不超過 grid item 的個數),而後設置的 grid-template-row
參數就是每一列的高度(超出列數的高度無效)
好比:
.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;
}複製代碼
雖然咱們設置了四個 grid-template-rows
,可是由於只有兩行,因此只有前兩個值生效。效果以下:
固然,咱們也能夠像 flex 同樣設置每一列的寬度:
.grid-container{
padding: 20px;
display: grid;
grid-template-rows: 50px 100px 60px;
grid-template-columns: 1fr 1fr 2fr;
background: pink;
}複製代碼
注意到咱們使用了一個新的單位:fr
css fr 單位是一個自適應單位,fr單位被用於在一系列長度值中分配剩餘空間,若是多個已指定了多個部分,則剩下的空間根據各自的數字按比例分配。
tips:fr 是基於網格容器可用空間來計算的(flex 也是同樣),因此咱們能夠和其餘單位混合使用,若是須要的話
是否是找到了 flex 的感受,這樣設置效果以下:
minmax()
函數來建立行或列的最小或最大尺寸,第一個參數定義網格軌道的最小值,第二個參數定義網格軌道的最大值。能夠接受任何長度值,也接受 auto
值。auto
值容許網格軌道基於內容的尺寸拉伸或擠壓。
.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;
}複製代碼
咱們將第一行的高度設置爲 minmax(100px,200px)
,第二行的高度設置爲minmax(50px,200px)
,容器總高度設置爲 300px
,這時每一列的高度要怎麼算呢?
先判斷總高度是小於第一列高度的最大值和第二列高度的最大值之和的,若是大於最大值之和,那麼第一列和第二列的高度都爲設置的最大值,若是是小於最小值之和的話,那麼第一列和第二列的高度都爲設置的最小值。
如今問題來了,咱們這種狀況是總高度是小於第一列高度的最大值和第二列高度的最大值之和的,這樣就是先用 總高度 300px
- 第一列最小高度 100px
- 第二列最小高度 50px
= 150px
。
第一列高度:第一列最小高度 100px
+ 150px/2
= 175px
;
第二列高度:第一列最小高度 50px
+ 150px/2
= 125px
;
效果以下:
repeat()
屬性能夠建立重複的網格軌道。這個適用於建立相等尺寸的網格項目和多個網格項目。
repeat()
也接受兩個參數:第一個參數定義網格軌道應該重複的次數,第二個參數定義每一個軌道的尺寸。
.grid-container{
padding: 20px;
display: grid;
grid-template-columns: repeat(2,100px);
grid-template-rows: repeat(3,100px);
background: pink;
}複製代碼
效果以下:
grid-column-gap
:建立列與列之間的距離。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
兩個屬性的縮寫。
咱們能夠經過表格線行或者列來定位 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
縮寫,分別對應 grid-row-start
、grid-column-start
、grid-row-end
、grid-column-end
:
grid-area: 2 / 2 / 3 / 3;複製代碼
這個就和 excel 中的合併單元行/列是相同的(這個須要設置在 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
簡寫的形式,關鍵詞 span
後面緊隨數字,表示合併多少個列或行,/
前面是從第幾行/列開始。
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;
}複製代碼
效果如圖:
在 grid 中,是能夠自定義網格線的名稱的,而後使用定義好的網格線來進行佈局,[col1-start]
網格線名稱必定要使用 []
括住。
<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;}複製代碼
最後的顯示效果是這樣的(文字和輔助線是後臺添加的):
網格區域(grid-area)是一個邏輯空間,主要用來放置一個或多個網格單元格(Grid Cell)。他是由四條網格線(Grid line),網格區域每邊一條,四邊相交組織的網格軌道(Grid Track)。簡單點理解,網格區域是有四條網格線交織組成的網格空間,這個空間中多是一個網格單元格,也多是多個網格單元格。
在CSS Grid Layout中定義網格區域有兩種方式,一種是經過網格線來定義,另外一種是經過grid-template-areas來定義。接下來看看兩種定義網格區域的方法在具體使用過程當中有何不一樣。
使用網格線定義網格區域的方法很是的簡單,首先依賴於 grid-template-columns
和 grid-template-rows
顯式定義網格線,甚至是由瀏覽器隱式建立網格線,而後經過 grid-area
屬性經過取網格線,組成網格線交織區域,那麼這個區域就是所講的網格區域。在使用 grid-area
屬性調用網格線,其遵循的規則是 grid-area: row-start
/ column-start
/ row-end
/ column-end
。
grid-template-areas
定義網格區域除了使用網格線的交組來定義網格區域以外,在 CSS Grid Layout 中還能夠經過 grid-template-areas
屬性來定義網格區域的名稱,而後須要放在對應網格區域的元素,能夠經過 grid-area
屬性來指定。並且重複區域可使用同一個名稱來實現跨區域。另外對於空的軌道區域,可使用點號 .
來表明
<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}複製代碼
我發現這樣佈局的一個優勢,在不設置高度的狀況下(父容器和 grid-template-rows
的值,或者 grid-template-rows
設置爲 auto
時,slider
和 content
的高度是一致的,而且會根據其內的高度自適應)
例如:
在介紹了 CSS 的佈局方式以後,咱們來看一下經常使用的 CSS 佈局有哪些
感受垂直居中真的是已經被講爛了,可是在平時作項目時,我都是靠試的,致使面試的時候被問到有時候回答不上來,如今就用本身的方式來總結一下。其實這個方式是有不少的,但就是看的教程太多了,致使最後一個都沒有記住,因此我決定儘量的將狀況考慮完整,而後每一種狀況只記住一個最佳實踐。
對於居中,我我的認爲不須要背什麼「x 種方式實現 xx」這樣的例子,咱們只須要了解其原理便可寫出符合要求的 css。
水平、垂直居中,我的比較喜歡用絕對定位的方法實現,其次就是使用 table
佈局,由於自帶垂直居中。若是是單行的行內元素使用 line-height
等於 height
,對於多行元素的垂直居中,大部分都是使用 table
元素(求推薦更好的佈局),固然還有 flex 和 grid 佈局。
通常水平居中仍是比較容易的,我通常都是先看子元素是固定寬度仍是寬度未知
這種方式是絕對定位居中,除了使用 margin
,咱們還可使用 transform
(注意瀏覽器兼容性,只適用於 ie9+,移動開發請忽略)
.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
;但通常狀況下我都會使用上一種,由於習慣了(ಥ_ಥ)
將子元素設置爲行內元素,而後父元素設置 text-align: center
。
.container{
width: 300px;
height: 200px;
background: pink;
position: relative;
text-align: center;
}
.inner{
display: inline-block;
}複製代碼
上面的方式即便子元素不止一個也想實現水平居中也是有效的,(寬度固定不固定均可,不固定的話就不須要設置寬度,會被自動撐開,可是要考慮到撐爆的狀況)例如:
.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;
}複製代碼
固然也可使用咱們剛剛介紹的 flex,咱們只須要讓子元素在主軸上的對齊方式設置爲居中就能夠
.container{
width: 250px;
height: 200px;
background: pink;
display: flex;
justify-content: center;
padding: 20px;
}
.inner{
background: #fff;
width: 50px;
height: 150px;
margin-left: 10px;
}複製代碼
單行海內元素居中,只須要將子元素的行高等於高度就能夠了。
#container {
height: 400px;
background: pink;
}
#inner{
display: inline-block;
height: 200px;
line-height: 200px;
}複製代碼
上面的這種方式只能處理單行的行內元素,對於多行的行內元素是處理不了的,由於給每個子元素都設置了 line-height
,看了不少方法,要不是沒有效果,要否則就是又侷限性,提到最多的是使用 table-cell
的方式(可是貌似這個方法也有一點弊端,那就是其子元素的表現形式和行內元素相似,子元素不能獨佔一行),固然若是你有更好的方式,歡迎提出:
.container {
width: 200px;
height: 400px;
background: pink;
position: absolute;
display: table;
vertical-align:middle;
}
.inner{
display: table-cell;
vertical-align:middle;
}複製代碼
還有一個方法是設置一個空的行內元素,使其 height:100%
,display:inline-block
,vertical-align: middle;
而且 font-size:0
。可是這樣方式的原理我還不是很清楚,只是知道要設置一個空元素,高度和父元素相等,而且設置垂直居中的屬性。可是,這只是用與全部的行內元素的寬度和不超過父元素的寬度的狀況。
<div class="container">
<img src="WechatIMG110.jpg" width="50px" />
<img src="WechatIMG110.jpg" width="50px" />
<img src="WechatIMG110.jpg" width="50px" />
<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;
}複製代碼
效果:
常常有看到設計稿是圖片和文字垂直居中的,那麼怎麼才能讓圖片和文字垂直居中呢?
只須要給圖片一個 vertical-align: middle;
屬性就能夠:
<div class="container">
<img src="WechatIMG110.jpg" height="260" />
<p>123456</p>
</div>複製代碼
.container {
background: pink;
padding: 20px;
height: 400px;
}
.container img{
display: inline-block;
vertical-align: middle;
}
.container p{
display: inline-block;
}複製代碼
效果以下:
自我感受總結的居中問題不是特別的好,咱們如今能夠來總結一下其中的原理:
text-align:center
了,可是這個只對行內元素有效,因此咱們要使用 text-align:center
就必須將子元素設置爲 display: inline;
或者 display: inline-block;
;text-align
那麼會不會對應也有自帶垂直居中的呢,答案是有的 vertical-align:
,我一直不是很喜歡使用這個屬性,由於十次用,9.9 次都沒有垂直居中,一度讓我懷疑人生。如今貌似也搞得不是很清楚,看了 張鑫旭的文章 竟然看得也不是很懂,笑哭。目前就在 table
中設置有效,由於 table
元素 的特性,打孃胎裏面帶的就是好用。還有一種能夠有效的方式是前面提到的空元素的方式,不過感受多設置一個元素還不如使用 table
。line-height
和 height
設置爲相同(只適用於單行行內元素)position:reletive
對應的子元素要設置 position:absolute
,而後使用 top:50%;left:50%
,將子元素的左上角和父元素的中點對齊,以後再設置偏移 margin-top: 1/2 子元素高度;margin-left: 1/2 子元素寬度;
。這種方式也很好理解。margin
改成 transform
就能夠實現寬度和高度未知的居中(兼容性啊兄弟們!(ಥ_ಥ))transformX:50%;transformY:50%
;不行,感受總結的仍是很渣,╮(╯▽╰)╭哎,誰有好的方法,求推薦。
其實我還真是第一次據說聖盃佈局這種稱呼,看了下這個名字的由來,貌似和佈局並無什麼關係,聖盃佈局卻是挺常見的三欄式佈局。兩邊頂寬,中間自適應的三欄佈局。
效果以下:
這個佈局方式的關鍵是怎麼樣才能使得在伸縮瀏覽器窗口的時候讓中間的子元素寬度改變。能夠適應瀏覽器的寬度變化使用百分比設置寬度再合適不過,因此咱們要將中間子元素的寬度設置爲 100%
,左邊和右邊的子元素設置爲固定的寬度。
咱們就來實現一下這樣的佈局:
HTML 文件就很普通:
<div class="container">
<div class="middle">測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試測試</div>
<div class="left">left</div>
<div class="right">right</div>
</div>複製代碼
這裏咱們要注意的是,中間欄要在放在文檔流前面以優先渲染。
而後咱們寫 CSS,咱們現將其三個元素的寬度和高度設置好,而後都設置爲 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;
}複製代碼
這時的效果以下:
咱們能夠看出,如今三個子元素是在一排顯示的,由於咱們給中間的子元素設置的寬度是 100%
,而且中間的子元素在文檔流的最前面,最早被渲染。
那麼咱們要使得三個元素在同一排顯示。接下來咱們要將 .left
和 .right
向上提。實際上咱們是使用 margin-left
爲 負值來實現的,咱們將 .left
的 margin-left
設置爲 -100%
(負的中間子元素的寬度),這樣,左邊的元素就會被「提高」到上一層。
而後就是右邊子元素了,只須要設置 margin-left
設置爲負的自身的寬度。
結果以下:
從上一張截圖顯示中顯示中間的子元素被遮擋了,因此說咱們要解決這個問題,要怎麼解決呢?嗯... 只要使得中間的子元素顯示的寬度恰好爲左邊元素和右邊元素顯示中間的寬度就能夠。同時咱們還必須保證是使用的半分比的佈局方式。
這樣的話有一種方式能夠即便中間的寬度減小,又可使中間的寬度仍然使用 100%
,那就是設置父元素的 padding
值,將父元素的 padding-left
設置爲左邊子元素的寬度,將父元素的 padding-right
設置爲右邊子元素的寬度。
顯示效果以下:
嗯... 這貌似也不是咱們想要的效果,可是,中間的子元素確實是在中間了,那麼咱們只須要設置相對位置,將左邊的子元素和右邊的子元素向兩邊移動就好。
最終的 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;
}複製代碼
最終效果以下:
其實雙飛翼佈局是爲了解決聖盃佈局的弊端提出的,若是你跟我一塊兒將上面的聖盃佈局的代碼敲了一遍,你就會發現一個問題,當你將瀏覽器寬度縮短到必定程度的時候,會使得中間子元素的寬度比左右子元素寬度小的時候,這時候佈局就會出現問題。因此首先,這提示了咱們在使用聖盃佈局的時候必定要設置整個容器的最小寬度。
聖盃佈局和雙飛翼佈局解決問題的方案在前一半是相同的,也就是三欄所有float浮動,但左右兩欄加上負margin讓其跟中間欄div並排,以造成三欄佈局。
不一樣在於解決」中間欄div內容不被遮擋「問題的思路不同:聖盃佈局,爲了中間div內容不被遮擋,將中間div設置了左右padding-left和padding-right後,將左右兩個div用相對佈局position: relative並分別配合right和left屬性,以便左右兩欄div移動後不遮擋中間div。
雙飛翼佈局,爲了中間div內容不被遮擋,直接在中間div內部建立子div用於放置內容,在該子div裏用margin-left和margin-right爲左右兩欄div留出位置。
做者:知乎用戶
連接:www.zhihu.com/question/21…
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
因此只是一個小小的改動
<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;
}複製代碼
這樣,在咱們將中間元素寬度調到比兩邊元素小的時候,也是能夠正常顯示,可是若是總寬度小於左邊元素或者右邊元素的時候,仍是會有問題。
若是你已經看到了這裏,那麼很感謝,已經到最後了,我認可,這篇文章真的很長...
因此,來,打起精神,對於下面的佈局方式,你們都什麼好的佈局方式或者奇淫技巧呢~
其實我只是想知道左邊頭像和下面的文字垂直居中有什麼好的方法。
此問題能夠簡化爲,多個未知高度的元素如何垂直居中?對了,不使用 flex 和grid 佈局,要求兼容 ie8+。
你們捧個場,能夠直接發郵件將你的代碼發給我,我郵件地址:991939332@qq.com,謝謝你們,謝謝謝謝