原文:https://dev.opera.com/articles/advanced-cross-browser-flexbox/
介紹
CSS靈活盒子產品級3 -簡稱Flexbox-它為web開發帶來了很多的動力和一些非常令人興奮的可能性,使我們能夠在一些複雜的站點布局很容易和迅速,摒棄一些不合邏輯的hacks群組裝件我們傳統上使用。我在文章Flexbox中處理了Flexbox的基礎知識:快速布局必殺技?在本文中,我将進一步讨論一個更進階的示例,并使用Modernizr為具有不同Flexbox支援級别的浏覽器提供不同的樣式,進而提供目前可用的最佳跨浏覽器支援級别。
介紹這個例子
我為本文建構的示例如圖1所示:
圖1:最終布局示例的圖像
其中包含多個級别的Flexbox。如果您願意,可以實時檢視示例,并繼續閱讀以更詳細地探索代碼。
整體布局
該網站的基本布局如下:
<section>
<nav></nav>
<article></article>
<article></article>
</section>
将
<section>
設定為display,就像這樣的彈性盒:
section {
display: -ms-Flexbox;
-ms-box-orient: horizontal;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flex;
display: flex;
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
}
注意:規則頂部指定了不同的IE特定屬性,因為IE10目前支援不同的Flexbox文法(從2011年開始)到Opera和Chrome支援的最新規範。更糟糕的是,Firefox和其他WebKit浏覽器(如Safari)支援更老版本的文法(從2009年開始)。最重要的是,Modernizr報告IE10支援現代Flexbox,即使它不支援,是以我們需要像這樣處理IE10,而不是Modernizr規則。有關詳細資訊和說明,請參閱下面的Flexbox智能後備部分。
我正在使 flow horizontal,但強制
<nav>
使用以下規則固定在自己的行上:
nav {
padding: 1rem;
-webkit-flex: 1 100%;
-moz-flex: 1 100%;
-ms-flex: 1 100%;
flex: 1 100%;
}
設定
flex-basis
為
100%
使其占據其父級寬度的100%,進而強制其他Flexbox子級換行到新行。該
<article>
的設定
flex-grow
值如下:
article:nth-of-type(1) {
-webkit-flex: 2;
-moz-flex: 2;
-ms-flex: 2;
flex: 2;
}
article:nth-of-type(2) {
-webkit-flex: 3;
-moz-flex: 3;
-ms-flex: 3;
flex: 3;
}
它們将占據一行空間的那一部分 - 第一個
<article>
跨越40%,或寬度的2/5,第二個
<article>
(圖像容器)跨越寬度的60%或3/5 。這是值得記住的 - 比例值隻占item所在行上的空間的比例,而不是子級所在行的所有行。
注意:
flex-basis
指定的值首先應用于Flexbox子元素; 之後,父級留下的空間根據
flex-grow
比例值在子級之間劃分。如果
flex-grow
沒有明确設定值,就像
nav
上面的規則集一樣,它預設為1.有關這些工作原理的更多資訊,請閱讀我的快速跟蹤布局的必殺技?文章。
Child flexboxes
當你将一個元素設定為一個靈活的盒子時,它隻會flex它的直接子節點而不是其他後代。但是沒有什麼可以阻止你使一些非常複雜的布局讓那些後代變成靈活的盒子!在這裡,我也設定了
<nav>
一個Flexbox,是以我可以有效地集中它,而不必擔心它有多寬:
nav {
display: -ms-flexbox;
-ms-box-orient: horizontal;
-ms-box-pack: center;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flex;
display: flex;
-webkit-justify-content: center;
-moz-justify-content: center;
-ms-justify-content: center;
justify-content: center;
}
然後我也
<ul>也做出
一個靈活的盒子,把他們的子級
<li>
包裝起來并居中:
nav ul {
text-align: center;
display: -ms-flexbox;
-ms-box-orient: horizontal;
-ms-box-pack: center;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flex;
display: flex;
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-justify-content: center;
-moz-justify-content: center;
-ms-justify-content: center;
justify-content: center;
width: 80%;
}
nav a {
width: 100%;
}
我還添加了一些其他屬性來整理這些導航項的外觀。我希望
<ul>
不會完全在螢幕上展開那些都居中的文字,是以我給自己定
width: 80%
和
text-align: center
; 我也确
<li>
的整個寬度
width: 100%
。
接下來是神奇的時刻。此時清單項看起來有點重疊和奇怪,當它們開始換行時它們看起來很愚蠢。一個看起來很酷、不需要媒體查詢的響應式菜單怎麼樣?所需要的隻是以下規則:
nav ul li {
margin: 0 1.5rem;
-webkit-flex: auto;
-moz-flex: auto;
-ms-flex: auto;
flex: auto;
min-width: 5rem;
}
在這裡,我給清單項目一些喘息的空間
margin
,給他們一個
min-width
,并設定
flex
為
auto
。這是flex的一個特殊值,它允許flex子項尊重
min-width
類型值,并在沒有多餘空間時保持不變的大小,但是當有多餘的空間可以用時,就會擴充它以填充多餘空間。看看展開和收縮頁面時會發生什麼(如圖2所示)?
圖2:神奇的伸縮靈活菜單!
我也flex了第二個
<article>
,并将其中的段落像這樣排列(每個段落都包含一個圖像):
article:nth-of-type(2) {
display: -ms-flexbox;
-ms-box-orient: horizontal;
-ms-box-pack: center;
-ms-box-align: center;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flex;
display: inline-flex;
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-justify-content: center;
-moz-justify-content: center;
-ms-justify-content: center;
justify-content: center;
-webkit-align-items: center;
-moz-align-items: center;
-ms-align-items: center;
align-items: center;
-webkit-align-content: flex-start;
-moz-align-content: flex-start;
-ms-align-content: flex-start;
align-content: flex-start;
}
article p {
margin: 0.5rem;
-webkit-flex: 1 20rem;
-moz-flex: 1 20rem;
-ms-flex: 1 20rem;
flex: 1 20rem;
}
article p img {
display: block;
width: 100%;
border: 1px solid black;
}
在這裡,我将它們設定為固定
flex-basis
值,是以随着寬度的增加和減少,它們将改變每行的數量(參見圖3 - 再次,不需要媒體查詢),并使item和item内容都在中間,水準和垂直。
圖3:一個很好的響應式圖像框,沒有媒體查詢
Flexbox的智能回退
對Flexbox的支援即将到來(WebKit浏覽器,基于Presto的Opera,Firefox支援有限,很快就會出現在其他人中!)但是在支援真正成為主流之前還需要一段時間。這意味着,如果我們想在生産代碼中使用Flexbox,我們現在需要使用一些智能替代方案。某些浏覽器(舊的WebKits和Firefox)支援2009年的舊版Flexbox文法。從2011年開始,IE10支援奇怪的新舊混合。幸運的是,Modernizr功能檢測庫具有現代Flexbox文法和傳統Flexbox文法的功能檢測功能
flexbox
,以及和
flexbox-legacy
标志。但還有一個問題 - Modernizr的測試報告IE10支援現代Flexbox,而不是Flexbox遺留。它實際上也不支援 - 它支援中間文法!這就是為什麼我們在主要CSS規則中将IE10特定屬性放在我們的代碼中,而不是在下面将看到的Modernizr代碼塊中處理它們。
注意:有關如何處理Modernizr Flexbox IE10檢測問題的讨論,截至2013年4月仍在進行中。
下表提供了現代Flexbox文法的摘要,以及2009和2011混合文法中的等效文法:
最終文法 | 2009文法 | 2011混合文法 |
---|---|---|
display: flex | display: box | display: flexbox |
flex-direction: row | box-orient: horizontal | box-orient: horizontal |
justify-content: flex-start | box-pack: start | box-pack: start |
align-items: flex-start | box-align: start | box-align: start |
flex: 1 | box-flex: 1 | flex: 1 |
注意:
box-lines
2009規範中有一個屬性,看起來相當于
flex-wrap
,但遺憾的是,任何支援舊文法的浏覽器似乎都不支援這一屬性。是以我的例子不起作用,是以我不得不為舊浏覽器簡化它。
是以我在我的示例中為不支援Flexbox的浏覽器提供了以下後備樣式,但是支援Flexbox遺留:
/* legacy Flexbox fallback */
.no-flexbox section {
display: -webkit-box;
display: -moz-box;
-webkit-box-orient: horizontal;
-moz-box-orient: horizontal;
}
.no-flexbox nav {
padding: 1rem;
width: 20%;
}
.no-flexbox article {
-webkit-box-flex: 1;
-moz-box-flex: 1;
}
.no-flexbox article p {
float: left;
}
.no-flexbox article img {
display: block;
width: 200px;
}
對于那些甚至不支援傳統Flexbox的浏覽器,我們已經有了以下内容:
.no-flexbox-legacy nav, .no-flexbox-legacy article {
float: left;
}
.no-flexbox-legacy nav {
width: 20%;
}
.no-flexbox-legacy article {
width: 36%;
}
.no-flexbox article img {
float: left;
}
注意:生成跨浏覽器Flexbox代碼并了解不同浏覽器使用的文法的一種好方法是使用Flexy Boxes工具。
為窄屏和寬屏布局添加簡單的媒體查詢
最後,我決定放入幾個媒體查詢,隻是為了修複窄螢幕寬度的布局。但請注意媒體查詢中的代碼是多麼的小:Flexbox建立的布局在不同的螢幕寬度本來就非常靈活。
首先,對傳統Flexbox布局進行簡要修複:
@media all and (max-width: 600px) {
h1 {
font-size: 5rem;
}
.no-flexbox section {
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
}
.no-flexbox nav {
width: 100%;
margin-left: -3rem;
}
.no-flexbox nav a, .no-flexbox nav ul, .no-flexbox nav li {
width: 100%;
}
}
接下來,在小螢幕寬度的情況下,對現代的Flexbox和沒有flex的所有浏覽器進行修複。
@media all and (max-width: 480px) {
article:nth-of-type(1) {
-webkit-flex: 1 100%;
-moz-flex: 1 100%;
-ms-flex: 1 100%;
flex: 1 100%;
}
body {
min-width: 320px;
}
nav ul {
width: 100%;
}
.no-flexbox-legacy nav, .no-flexbox-legacy article {
float: none;
}
.no-flexbox-legacy nav, .no-flexbox-legacy article {
width: 100%;
}
}
最後,媒體查詢隻是将内容集中在寬螢幕上。
@media all and (min-width: 1100px) {
section {
width: 1100px;
margin: 0 auto;
}
}
結論
目前使用Flexbox是有局限性的,而且當所有現代浏覽器都以同樣的方式支援Flexbox時,使用它會更容易。就目前而言,堅持使用Flexbox的更簡單的單行功能要有效得多,因為多行Flexbox在支援legacyflex的浏覽器中并不能真正有效地實作。按照标準,我的示例運作得不錯,盡管傳統布局不如現代的Flexbox布局好;另一個有趣的問題是,Firefox似乎拒絕将已經作為Flexbox布局的内容放在中心,使用的是“
margin: 0 auto
”(在Safari中,居中效果很好)。
但是,對于簡單的Flexbox使用,你可以在各種現代浏覽器上運作良好:Chrome,Firefox,Safari,Opera Presto 12.1 +,IE 10 +,iOS和Android。