Flex 布局

Flex 是 Flexible Box 的縮寫,意為"彈性布局",它旨在提供一種更有效的方式來布局、對齊和分配容器中項目之間的空間,即使這些項目的大小未知或是動態(因此稱為 "flex")。

Flex 布局背后的主要思想是讓容器能夠改變其項目的寬度/高度(和順序),以最好地填充可用空間(主要是為了適應各種顯示設備和屏幕大小)。flex 容器擴展項目以填充可用空間,或收縮項目以防止溢出。

最重要的是,Flexbox 布局與常規布局(基于垂直的塊和基于水平的內聯)相比是方向無關的。雖然這些方法對頁面很有效,但它們缺乏靈活性來支持大型或復雜的應用程序(尤其是在方向改變、調整大小、拉伸、收縮等方面)。

Flex 布局在2009年由 W3C 提出的。它在所有的瀏覽器都支持。

Flex 兼容情況

注意:Flexbox 布局最適合應用程序的組件和小規模布局,而 Grid 布局則適用于大規模布局。我們將在下一篇講解 Grid 布局。

以下內容參考 Flexbox30,圖片截自 A Complete Guide to Flexbox

基礎概念

為了使 Flexbox 正常工作,您需要設置父子關系。父級是 Flex 容器,其中的所有內容都是子級或 Flex 項。

Flex 容器僅環繞其直接子容器。因此,沒有孫子或孫子孫輩的關系。只有父母??直系子女!只要存在父子關系,就可以建立 Flexbox。因此,孩子也可以成為其孩子的伸縮容器。但這將是一個單獨的 flex 容器。而且它不會繼承祖父母的 flex 屬性。

這里有一篇關于不能將文本容器設置為 flexbox 容器 Never make your text container a flexbox container

img

Flexbox 在2軸系統中運行:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸是您將伸縮項目如何放置在伸縮容器中的定義方向。確定橫軸非常簡單,它是在垂直于主軸的方向上進行的。

記住不要把他比作數學上的 xy 軸。因為 x 軸并不總是主軸。這可能會讓你出錯。

在每個軸上都有一個起點和終點。如果在主軸上,則將起始位置稱為 main start,將結束位置稱為 main end。相同的概念適用于交叉軸。知道開始和結束很重要,因為您可以控制彈性項目的放置位置。

項目默認沿主軸排列。單個項目占據的主軸空間叫做 main size,占據的交叉軸空間叫做 cross size

屬性

父容器和子項目都有自己的一套屬性。

父容器

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

子項目

  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • order
  • align-self

父容器

父容器

flex 容器有2種類型:flex 將創建一個塊級 flex 容器,inline-flex 將創建一個 inline 級 flex 容器。

.parent {
  display: flex /* default */ | inline-flex;
}

很簡單地解釋,塊元素占據了容器的整個寬度。它們看起來像構建塊,其中每個構建塊彼此堆疊。內聯元素僅占用其所需的空間。因此,它們似乎排成一行,或者彼此并排。

flex-wrap

默認情況下,彈性項目將嘗試使其自身收縮以適合一行,換句話說,不進行換行。但是,如果您希望 flex 項保持其大小并在容器中的多行中溢出,則可以使用 flex-wrap: warp;。此屬性將使容器中的彈性項目占用多行。

.parent {
  flex-wrap: nowrap /* default */ | wrap | wrap-reverse;
}
flex-wrap

flex-wrap 允許 flex 項在單獨的行上進行包裝。但有了 align-content,我們可以控制那些項目行在橫軸上的對齊方式。由于這僅適用于包裝的項目,所以如果只有一行 flex 項,則此屬性不會有任何效果。

flex-flow

flex-flowflex-directionflex-wrap 的簡寫。默認值為 row nowrap。如果僅設置一個值,則未設置的屬性將采用默認值。

.parent {
  flex-flow: row nowrap /* default */ | <flex-direction> <flex-wrap> | <flex-direction> | <flex-wrap>;
}

flex-direction

定義主軸的屬性。記住主軸可以是水平或垂直的。因此,如果我們希望主軸水平,則稱為行。如果我們希望它是垂直的,那就叫做專欄。另外,請記住我們有一個主要的起點和終點。我們只需添加一個反向后綴即可將我們的“主要起點”設置為反向。

.parent {
  flex-direction: row /* default */ | row-reverse | column | column-reverse;
}
flex-direction

justify-content

justify-content 設置沿主軸對齊的屬性。align-items 設置沿橫軸對齊的屬性。記住橫軸始終垂直于主軸。

.parent {
  justify-content: flex-start /* default */ | flex-end | center | space-around | space-between | space-evenly;
}
justify-content

主軸也可以垂直放置。在這種情況下,將 flex-direction 設置為 column。

.parent {
  flex-direction: column;
  justify-content: flex-start /* default */ | flex-end | center | space-around | space-between | space-evenly;
}

align-items

.parent {
  align-items: stretch /* default */ | flex-start | flex-end | center | baseline;
}
align-items

現在,讓我們看一下如果交叉軸水平放置,則彈性項目如何對齊。換句話說,伸縮方向是列。

.parent {
  flex-direction: column;
  align-items: stretch /* default */ | flex-start | flex-end | center | baseline;
}

align-content

align-content 屬性定義了多根軸線的對齊方式。如果項目只有一根軸線,該屬性不起作用。

.parent {
  align-content: stretch /* default */ | flex-start | flex-end | center | space-between | space-around;
}
align-content

space-evenly 和 space-around

space-evenly 中,彈性項目之間的空白空間始終相等。

space-evenly

但是,在 space-around 上,只有內部項目之間的間距相等。第一項和最后一項將僅分配一半的間距。使它的視覺外觀更加散布

space-around

子項目

子項目

order

默認情況下,彈性項目的顯示順序與在代碼中顯示的順序相同。但是,如果您要更改該怎么辦?沒問題!使用 order 屬性更改商品的順序。

.child {
  order: 0 /* default */ | <number>;
}
order

flex-grow

Flexbox 非常適合響應式設計。flex-grow 屬性允許我們的 flex 項在必要時增長。因此,如果我的容器中有多余的可用空間,我可以告訴某個特定項目按一定比例將其填滿。

.child {
  flex-grow: 0 /* default */ | <number>;
}
flex-grow

flex-shrink

如果有伸縮空間,flex-grow 將會擴展以填充額外的空間。相反 flex-shrink 當空間不足時將會控制 flex 項目縮小到適合的程度。請注意,數字越大,縮小幅度越大。

.child {
  flex-shrink: 1 /* default */ | <number>;
}

你可以在 flex-grow-calculationflex-shrink-calculation 查看瀏覽器如何幫我們自動處理 flex-growflex-shrink

flex-basis

使用 flex-basis 屬性,可以設置項目的初始大小。您可以將此屬性視為 flex 項目的寬度。

因此,您的下一個問題可能是 widthflex-basis 之間的區別是什么。當然,您仍然可以使用 width,它將仍然有效。

它起作用的原因是,如果未設置 flex-basis,它將默認為 width。因此,您的瀏覽器將始終嘗試將 flex-basis 值用作大小指示器。如果找不到它,那就別無選擇,只能使用您的 width 屬性。不要讓瀏覽器做額外的工作。以正確的 flex 方法進行操作,并使用flex-basis

.child {
  flex-basis: auto /* default */ | <width>;
}

當一個項目具有 flex-basiswidth 時,瀏覽器將始終使用 flex-basis 設置的值。但要注意,如果同時設置了 min-widthmax-width。在這些情況下,flex-basis 將丟失,并且不會用作寬度。

flex

flex 是上面所提到的 flex-growflex-shrinkflex-basis 的簡寫形式。如果你足夠了解它們的特性,請使用簡寫吧!!!

.child {
  flex: 1 0 auto /* default */ |
      <flex-grow> <flex-shrink> <flex-basis> |
      <flex-grow> |
      <flex-basis> |
      <flex-grow> <flex-basis> |
      <flex-grow> <flex-shrink>;
  
  /* 相當于: */
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: auto;
}

align-self

align-items 屬性可以沿著橫軸設置 flex 項。align-items 的問題是它強制所有 flex 項使用規則。

但是如果你想讓他們中的一個打破規則,你可以使用 align-self。此屬性接受為 align-items 提供的所有相同值,因此您可以輕松脫離包裝??

.child-1 {
  align-self: stretch /* default */ | flex-start | flex-end | center | baseline;
}
align-self

技巧

垂直水平居中元素

方式一

.container {
  display: flex;
  justify-content: center; /* horizontal */
  align-items: center;     /* vertical */
}

方式二

.container {
  display: flex;
}

.container > div {
  margin: auto;
}
水平垂直居中

對齊 Flexbox 子元素的另一種方法是使用自動頁邊距。盡管這不是 Flexbox 屬性,但要意識到這一點仍然很重要,因為它與 Flexbox 有非常有趣的關系。Bonus: Aligning with Auto Margins

重新排序

.container > .top {
 order: 1;
}

.container > .bottom {
 order: 2;
}

截斷文本

.parent {
  display: flex;
  align-items: center;
  padding: 10px;
  margin: 30px 0;
}

.child {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.child > h2 {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.truncated {
  flex: 1;
  h2 {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

查看效果

移動布局

創建固定高度的頂欄和動態高度的內容區域。

.container {
  display: flex;
  flex-direction: column;
}

.container > .top {
  flex: 0 0 60px;
}

.container > .content {
  flex: 1 0 auto;
}

流式布局

自動用適當數量的盒子填充可用空間。

.container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 1rem;
}

.container > * {
  flex: 1 1 10ch;
}
流式布局

查看效果

響應導航欄

.nav {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-end;
  
  list-style: none;
  margin: 0; 
  background: deepskyblue;
}

.nav a {
  text-decoration: none;
  display: block;
  padding: 1em;
  color: white;
}

.nav a:hover {
  background: #1565C0;
}

@media all and (max-width: 800px) {
  .nav {
    justify-content: space-around;
  }
}

@media all and (max-width: 600px) {
  .nav {
    flex-flow: column wrap;
    padding: 0;
  }
  .nav a { 
    text-align: center; 
    padding: 10px;
    border-top: 1px solid rgba(255, 255, 255,0.3); 
    border-bottom: 1px solid rgba(0, 0, 0, 0.1); 
  }
  .nav li:last-of-type a {
    border-bottom: none;
  }
}

類似于表

.container {
  display: flex;
}

.container > .checkbox { 
  flex: 1 0 20px;
}
.container > .subject { 
  flex: 1 0 400px;
}
.container > .date { 
  flex: 1 0 120px;
}

這將創建寬度不同的列,但大小會根據具體情況而相應調整。

固定腳部

HTML 結構

<section>
  <header></header>
  <main></main>
  <footer></footer>
</section>

方式一

section {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

main {
  flex: 1;
}

方式二

section {
  display: flex;
  flex-direction: column;
}

footer {
  margin-top: auto;
}

砌體布局

.masonry-container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  max-height: 600px;
  .masonry-brick {
    margin: 0 .825rem .825rem 0;
    
    border-radius: 1rem;
  } 
}

/* or */

.masonry-container {
  display: flex;
  flex-wrap: wrap;
  .masonry-brick {
    flex: 1 0 auto;
    height: 150px;
    margin: 0 .825rem .825rem 0;
    border-radius: 1rem;
  } 
}
砌體布局

查看效果

圣杯布局

html 結構

<div class="container">
  <header class="header">Header</header>
  <article class="main">lorem</article>
  <aside class="aside aside-1">Aside 1</aside>
  <aside class="aside aside-2">Aside 2</aside>
  <footer class="footer">Footer</footer>
</div>

css

.container {
  display: flex;  
  flex-flow: row wrap;
  text-align: center;
}

.container > * {
  padding: 10px;
  flex: 1 100%;
}

.main {
  text-align: left;
}

@media all and (min-width: 600px) {
  .aside { flex: 1 0 0; }
}

@media all and (min-width: 800px) {
  .main    { flex: 3 0px; }
  .aside-1 { order: 1; } 
  .main    { order: 2; }
  .aside-2 { order: 3; }
  .footer  { order: 4; }
}

雙飛翼布局

雙飛翼布局其實是根據圣杯布局演化出來的一種布局。

.container {
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-around;
  height: 100%;
}

.left,
.right {
  width: 200px;
  flex-shrink: 1;
}

.main {
  flex-grow: 1;
}
雙飛翼布局

查看效果

兩列布局

.container {
  display: flex;
}

.left {
  width: 200px;
  height: 100%;
}

.right {
  flex: 1;
  height: 100%;
}
兩列布局

查看效果

更多資料

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容