Flex入坑指南

来源:https://www.cnblogs.com/jiasm/archive/2018/06/03/9130331.html
-Advertisement-
Play Games

彈性佈局flex是一個幾年前的CSS屬性了,說它解放了一部分生產力不為過。至少解放了不少CSS佈局相關的面試題 :) 之前網上流行的各種XX佈局,什麼postion: absolute+margin,float+padding,各種都可以使用flex來取代之。 早兩年在使用的時候,還是會擔心有相容性 ...


彈性佈局flex是一個幾年前的CSS屬性了,說它解放了一部分生產力不為過。至少解放了不少CSS佈局相關的面試題 :)
之前網上流行的各種XX佈局,什麼postion: absolute+marginfloat+padding,各種都可以使用flex來取代之。
早兩年在使用的時候,還是會擔心有相容性問題的,某些手機在使用了auto-prefixer以後依然會出現不相容的問題。
好在現在已經是2018年了,不必再擔心那些老舊的設備,希望這篇文章能幫你加深對flex的認識。

準備工作

首先,flex被稱為一個彈性盒模型,也有稱彈性佈局的。
總之,盒子也好、佈局也罷,我們總是需要有一個容器Container的:

<div class="container"></div>

 

以及如果單純的只是一個容器的話,是沒有任何意義的。
所以我們還需要有一些內容:

<div class="contianer">
  <div class="item"></div>
  <div class="item"></div>
</div>

 

下邊的所有例子基本都是基於以上DOM結構來做的。

基本語法

現在我們已經有一個可以用來寫flex佈局的html結構。
接下來就是一個最基礎的flex佈局的實現:

<style>
  .container {
    display: flex;
    height: 50px;

    color: #fff;
    border: 1px solid #03a9f4;
  }

  .item {
    flex: 1;

    text-align: center;
    background: #03a9f4;
  }
</style>
<div class="contianer">
  <div class="item"></div>
  <div class="item"></div>
</div>

 

我們在容器上使用display: flex來告訴瀏覽器,這是一個flex佈局的開始。
然後給所有的item添加一個flex: 1的屬性,來表明,我們這裡邊的元素都是flex佈局中的內容,
我們會沿著主軸平分所有的區域,就這樣,我們已經實現了一個多列等寬佈局。

關於flex,最重要的就是要記住他有兩條軸線(主軸、交叉軸),絕大部分屬性都是依賴於軸線的方向。

 

 

圖片來自MDN

因為flex佈局分為了容器和內容兩塊,各自有各自的屬性,所以就先從容器類的說起。

容器相關的flex屬性

實現上邊的需求,是依賴於很多預設屬性值。
比如,為什麼我們的子元素會橫向的進行分割空間,而不是豎向的,這裡就用到了一個屬性的預設值:

flex-direction

flex-direction用於定義flex佈局中的主軸方向。
預設取值為row,是橫向的,表示從左到右,也就是說我們的所有子元素會按照從左到右的順序進行排列。
我們可以通過設置值為column來改變主軸的方向,將其修改為從上到下。(改變flex-direction的值會影響到一些相關的屬性,會在下邊說到)

flex-direction共有四個有效值可選:

  1. row 預設值,從左到右
  2. row-reverse 從右到左
  3. column 從上到下
  4. column-reverse 從下到上

P.S. 在React-Native中預設的主軸方向為column

所以說flex-direction的作用就是:定義容器中元素的排列方向

flex-wrap

該屬性用於定義當子元素沿著主軸超出容器範圍後,應該按照怎樣的規則進行排列。
該屬性只有簡單的三個取值:

  1. wrap 超出主軸範圍後換行顯示,換行方向按照交叉軸的方向來(預設情況下就是折行到下一行
  2. wrap-reverse 超出主軸範圍後換行顯示,但是方向是交叉軸的反向(也就是預設情況下第一行會出現在最下邊
  3. nowrap 即使超出容器也不會進行換行,而是嘗試壓縮內部flex元素的寬度(在下邊的子元素相關的屬性會講到

三種取值的示例:

flex-flow

flex-flow是一個簡寫的屬性,適用於上邊提到的flex-directionflex-wrap

語法:

selector {
  flex-flow: <flex-direction> <flex-wrap>;
}

 

justify-content

這個會定義我們的子元素如何沿著主軸進行排列,因為我們上邊是直接填充滿了父元素,不太能看出效果。
所以我們對代碼進行如下修改:

<style media="screen">
  .container {
    display: flex;
    width: 400px;

    color: #fff;
    border: 1px solid #03a9f4;
  }

  .item {
    /* flex: 1; */
    width: 100px;

    text-align: center;
    background: #03a9f4;
  }
</style>
<div class="container">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
</div>

 

將所有的子元素都改為固定的寬度,也就是說,如果父元素有剩餘空間的話,就會空在那裡。
justify-content的預設取值為normal,也可以認為就是start了,也就是根據主軸的方向(flex-direction)堆在起始處。

幾個常用的取值:

  1. center 必然首選的是center,能夠完美的實現沿主軸居中
  2. flex-start 沿著主軸從行首開始排列
  3. flex-end 沿著主軸從行末開始排列

以及幾個不太常用的取值:

  1. space-between 將剩餘空間在子元素中間進行平分,保證沿主軸兩側不會留有空白。
  2. space-around 將剩餘空間均勻的分佈在所有的子元素沿主軸方向的兩側,也就是說,主軸兩側也會有空白,但是必然是中間空白的1/2大小。
  3. space-evenly 將剩餘空間在所有元素之間平均分配,主軸兩側的空白麵積也會與中間的面積相等。

六種效果的示例:

Warning

有一點需要註意,justify-content的取值都是依照flex-direction所定義的主軸方向來展示的。
也就是說,center在預設情況下用於水平居中,在flex-direction: column-*時,則是作為垂直居中來展示的。

align-content

同樣的,align-content也是用來控制元素在交叉軸上的排列順序,但是既然會出現兩個屬性(align-itemsalign-content),勢必兩者之間會有一些區別。

因為align-content只能作用於多行情況下的flex佈局,所以取值會更接近額旋轉後的justify-content,同樣的可以使用space-between之類的屬性值。

因為取值基本類似,所以不再重覆上邊justify-content所列的表格,直接上效果:

align-items

align-items與上邊的justify-content類似,也適用於定義子元素的排列方式。
不同的是,align-items作用於交叉軸(也就是預設flex-direction: row情況下的從上到下的那根軸線)
目測平時用到的最多的地方就是水平居中吧(我現在懶的:只要有圖標、表單 & 文字 的單行混合,都會選擇align-items: center來實現:)

常用的取值:

  1. center 常用來做垂直(交叉軸)居中
  2. flex-start 沿著交叉軸的起始位置排列
  3. flex-endflex-start方向相反
  4. stretch 將元素撐滿容器的交叉軸寬度(在預設情況下,這裡指容器的高度,但是如果單純的說這條軸線,我覺得寬度更合適一些
  5. baseline 將元素按照文本內容的基線進行排列

以上取值的示例:

align-content與align-items的異同

兩者的相同點在於,都是設置元素在交叉軸上的排列順序。
而區別在於以下兩點:

  1. align-content只能應用於多行的情況下
  2. align-content會將所有的元素認為是一個整體併進行相應的處理、而align-items則會按照每一行進行處理:

  

 

place-content

place-content可以認為是justify-contentalign-content的簡寫了(事實上就是

語法為:

selector {
  place-content: <align-content> <justify-content>;
}

 

P.S. 如果單行(元素)想要實現居中還是老老實實的使用align-items+justify-content吧 :)

子元素的屬性們

有關容器的所有屬性都已經列在了上邊,下邊的一些則是在容器內元素設置的屬性。

flex-grow

flex-grow用來控制某個子元素在需要沿主軸填充時所占的比例,取值為正數(浮點數也可以的)。

selector {
  flex-grow: 1;
  flex-grow: 1.5;
}

 

舉例說明:
如果一個容器中有三個元素,容器剩餘寬度為100px,三個元素需要進行填充它。
如果其中一個元素設置了flex-grow: 2,而其他的設置為1(預設不設置的話,不會去填充剩餘寬度)
則會出現這麼一個情況,第一個元素占用50px,而其他兩個元素各占用25px。 

Warning

這裡需要註意的一點是,flex-grow定義的是對於剩餘寬度的利用。
元素自身占用的空間不被計算在內,為了驗證上邊的觀點,我們進行一個小實驗。
給每一個元素設置一個padding-left: 20px,保證元素自身占用20px的位置,然後分別設置flex-grow來查看最後元素的寬度是多少。

.container {
  display: flex;
  width: 160px;
  height: 20px;
  align-items: stretch;
}

.item {
  flex-grow: 1;
  padding-left: 20px;
}

.item:first-of-type {
  flex-grow: 2;
}

 

我們給容器設置了寬度為160px(為了方便的減去padding-left計算)。

最後得到的結果,設置了flex-grow: 2的元素寬度為70px,而設置flex-grow: 1的元素寬度為45px
在減去了自身的20px以後,50 / 25 === 2 // true

flex-shrink

flex-shrink可以認為是與flex-grow相反的一個設置,取值同樣是正數。
用來設置當容器寬度小於所有子元素所占用寬度時的縮放比例。
比如說,如果我們的容器寬為100px,三個元素均為40px,則會出現容器無法完全展示所有子元素的問題。
所以預設的flex會對子元素進行縮放,各個元素要縮放多少,則是根據flex-shrink的配置來得到的(預設為1,所有元素平均分攤
就像上邊的例子,如果我們還是三個元素,第一個設置了flex-shrink: 2,則最終得到的結果,第一個元素寬度為30px,其餘兩個元素的寬度為35px

.container {
  display: flex;
  width: 100px;
  height: 20px;
  align-items: stretch;
}

.item {
  width: 40px;
  /* flex-shrink: 1; it's default value */
  font-size: 0;
  background: #03a9f4;
}

.item:first-of-type {
  flex-shrink: 2;
}

  

 

flex-basis

這個屬性用來設置元素在flex容器中所占據的寬度(預設主軸方向),這個屬性主要是用來讓flex來計算容器是否還有剩餘面積的。
預設取值為auto,則意味著繼承widthdirection: column時是height)的值。 一般來講很少會去設置這個值。

flex

flex則是上邊三個屬性的簡寫,語法如下:

selector {
  flex: <flex-grow> <flex-shrink> <flex-basis>;
}

 

一般來講如果要寫簡寫的話,第三個會選擇設置為auto,也就是獲取元素的width

align-self

效果如同其名字,針對某一個元素設置類似align-items的效果。
取值與align-items一致,比如我們可以針對性的實現這樣的效果:

.center :first-child {
  align-self: stretch;
}

.flex-start :first-child {
  align-self: flex-end;
}

.flex-end :first-child {
  align-self: flex-start;
}

.stretch :first-child {
  align-self: center;
}

 

 

order

以及最後這裡還有一個order屬性,可以設置在展示上的元素順序。
取值為一個任意整數。

預設的取值為1,如果我們想要後邊的元素提前顯示,可以設置如下屬性:

.item:last-of-type {
  order: -1;
}

  

 

P.S. 這個順序的改變只是顯示上的,不會真正的改變html的結構,比如,你依然不能通過.item:last-of-type ~ .item來獲取它在視覺上後邊的兄弟元素
當order重覆時,按照之前的順序排列大小

總結

flex相關的屬性如何拆分以後,並不算太多。
腦海中有主軸和交叉軸的概念之後,應該會變得清晰一些。
關於上述所有屬性的一個簡單總結:

容器相關

屬性名作用
flex-direction 用來設置主軸的方向,最基礎的屬性,預設從左到右,此屬性一改,下列所有的屬性都要跟著改,真可謂牽一發而動全身
flex-wrap 設置元素超出容器後的換行規則,預設不換行
justify-content 設置沿主軸的排列規則
align-content 設置沿交叉軸的排列規則
align-items 以行(預設direction情況下)為單位,設置沿交叉軸的排列規則

元素相關

屬性名作用
flex-grow 當容器大於所有元素時,按什麼比例將剩餘空間分配給元素
flex-shrink 當容器小於所有元素時,元素按照什麼比例來縮小自己
flex-basis 很少用的屬性,設置在容器中的寬(高)
align-self 針對某些元素單獨設置align-items相關的效果
order 設置元素在顯示上的順序

簡寫

屬性名作用
flex-flow flex-directionflex-wrap的簡寫
place-content justify-contentalign-content的簡寫
flex flex-growflex-shrinkflex-basis的簡寫

以及文中所有的示例代碼都在這裡 code here

參考資料

  1. How Flexbox works (此文中的一些gif圖真心贊)
  2. Understanding Flexbox: Everything you need to know
  3. Learn CSS Flexbox in 5 Minutes

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、標準廣播:是一種完全非同步執行的廣播,在廣播發出之後,所有的廣播接收器幾乎會在同一時刻接收到這條廣播信息,它們之間沒有先後順序。效率高、無法被截斷。 2、有序廣播:是一種同步執行的廣播,在廣播發出後,同一時刻只會有一個廣播接收器能夠接收到這條廣播,當這個廣播接收器中的邏輯執行完畢後,廣播才會繼續傳 ...
  • //1.var定義的變數可以修改,如果不初始化會輸出undefined,不會報錯。 var a; console.log(a); //undefined //2.let是塊級作用域,函數內部使用let定義後,對函數外部無影響。 let c = 3; console.log(c) function c... ...
  • 可參考 http://blog.pandax.me/cjbk/ 此文 ...
  • 通過對img opacity樣式的修改,達到對img顯隱的控制,從而形成輪播 ...
  • 內容:Buffer與字元編碼,Buffer創建、寫入、讀取、轉換成JSON對象、合併、比較、拷貝、裁剪、長度 Buffer 與字元編碼Buffer 實例一般用於表示編碼字元的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六進位編碼的數據。 通過使用顯式的字元編碼,就可以在 Buffe ...
  • javascript中offsetWidth、clientWidth、width、scrollWidth、clientX、screenX、offsetX、pageX 原文:https://www.cnblogs.com/ifworld/p/7605954.html offsetWidth //返回元 ...
  • 剛開始學習JS不久,以及第一次來到博客園,第一次進行分享博文。。。 噢,不對,不能說是分享,而是學習請教,請前輩多多指教,各個方面都可以~ 感謝您的路過~ ...
  • CSS的權重如下: !important Infinity正無窮 行間樣式 1000 id 100 class|屬性|唯類 10 標簽|偽元素 1 通配符 0 256進位 當出現多個選擇器時 在同一行的選擇器權重相加即可 當兩個混合選擇器權重相同時優先選擇後面的選擇器 如: html <div cl ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...