【佈局技巧】Flex 佈局下居中溢出滾動截斷問題

来源:https://www.cnblogs.com/coco1s/archive/2023/12/07/17881159.html
-Advertisement-
Play Games

在頁面佈局中,我們經常會遇到/使用這麼一類常見的佈局,也就是列表內容水平居中於容器中,像是這樣: <ul class="g-contaner"> <li></li> <li></li> </ul> ul { width: 500px; display: flex; flex-direction: r ...


在頁面佈局中,我們經常會遇到/使用這麼一類常見的佈局,也就是列表內容水平居中於容器中,像是這樣:

<ul class="g-contaner">
    <li></li>
    <li></li>
</ul>
ul {
    width: 500px;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: center;
    gap: 10px;
}

效果如下:

這裡,外層的容器是定寬的,內層的 flex-item 也是定寬的。

當 flex-item 個數較小時,是沒有問題的。但是,如果當元素內容過多,並且設置了 flex-wrap: nowrap 的話,內容就會溢出容器:

此時,我們有幾種解法,其中一種便是給父容器設置 overflow: auto 或者 overflow: hidden,讓父容器可以滾動,像是這樣:

ul {
    // ...
    overflow: auto;
}

效果就變成了這樣:

我們嘗試滾動一下這個容器,會發現一個致命問題:容器只能向左滾動,無法向右滾動,因此只能看到後半部分被截斷的內容,而無法看到前半部分被截斷的內容

什麼意思呢?結合上面的 Gif 與下麵這張示意圖,一看就懂:

針對這個問題。其中一類比好好的解法在於,當 flex-item 不足以溢出時候,flex-item 居中展示,而當 flex-item 的數量溢出父容器寬度時候,佈局上採用類似於 justify-content: flex-start 的樣式進行排布,這樣可以保證內容在滾動的過程中能夠全部看到

正常效果應該如下:

上面第一、第二行就是 flex-item 不足以溢出時候,flex-item 居中展示, 而第三行 ,就是當 flex-item 的數量溢出父容器寬度時候,佈局上採用類似於 justify-content: flex-start 的樣式進行排布,這樣可以保證內容在滾動的過程中能夠全部看到。

因此,本文我們將一起探討一下,在面對這個問題時的幾種不同方式的解法。

方法一:Flex 佈局下關鍵字 safe、unsafe

其實,規範也已經註意到了佈局下的這個居中滾動問題。

因此,在從 Chrome 115 開始,flex 佈局下新增了兩個關鍵字 safeunsafe

基於 CSS Box Alignment Module Level 3,明確列出了這種安全(safe)不安全(unsafe) 的佈局說明:

而今天,我們可以直接在對齊模式中,通過 safe 關鍵字解決這個問題。

我們簡單改造一下上述我們的 flex 佈局代碼,將 justify-content: center 改為 justify-content: safe center 即可:

ul {
    width: 500px;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
 -  justify-content: center;
 +  justify-content: safe center;
    align-items: center;
    gap: 10px;
}

此時,flex 佈局就能自動識別當前 flex 容器下的 flex-item 數量是否超出容器寬度/高度,從而改變對齊方式

完整的代碼,你可以戳這裡自己感受:CodePen Demo -- 使用 Safe 關鍵字解決 Flex 居中溢出問題

目前而言,這個方法唯一的問題在於 相容性safe 關鍵字的大範圍使用,還需要靜待一段時間。

方法二:使用 margin: auto 替代 justify-content: center

因此,我們有必要繼續去探尋其它解決方案。

在之前,有發過另外兩篇 flex 相關技巧性的文章 --

  1. 探秘 flex 上下文中神奇的自動 margin - 掘金
  2. 水平垂直居中深入挖掘 - 掘金

除去 justify-content: center 之外,其實我們還可以利用 margin: auto 實現子 flex-item 的水平居中。

我們改造一下文章一開始的示意 DEMO:

ul {
    width: 500px;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    gap: 10px;
}
li {
    margin: auto;
}

當,flex-item 數量不足以溢出容器寬度時,效果如下:

此時,flex-item 在 margin: auto 的作用下,會均分整個容器的剩餘空間,並且是水平和垂直方向上的。

用規範的話說就是,設置了 margin: auto 的元素,在通過 justify-contentalign-self 進行對齊之前,任何正處於空閑的空間都會分配到該方向的自動 margin 中去。

所以,margin: auto 也是一種居中非常重要的技巧,雖然我們常將這個技巧用於 flex 佈局下的垂直居中。可以翻看一下上面提供的兩篇文章。

有趣的是,當 flex-item 的數量溢出父容器寬度時候,由於沒有剩餘空間了,此時 margin: auto 其實相當於失效了,因此佈局上的效果同樣也是採用類似於 justify-content: flex-start 的效果進行排布。

同樣能達到我們的目的:

完整的代碼,你可以戳這裡自己感受:CodePen Demo -- 使用 margin:auto 解決 Flex 居中溢出問題

方法三:額外嵌套一層

上面的 margin:auto 雖然沒有相容性問題,但是有一點點瑕疵。我們仔細對比 margin: autojustify-content: center 在 flex-item 不足以溢出下的表現:

瑕疵在於,使用 margin: auto 的方式,flex-item 之間的間距是不可控。因為它們始終會去平分剩餘空餘空間。

2023-12-06 更新,基於 margin: auto 不可控的方式,其實通過只給子 item 的首個元素添加 margin-left: auto,給尾元素添加 margin-right: auto,其實是可以解決間距問題的。

所以,相容性最好的方式,就是我們多疊加一層,同樣可以巧妙的解決這個問題。

原結構:

<ul class="g-contaner">
    <li></li>
    // ...
    <li></li>
</ul>

改造後的結構:

<ul class="g-contaner">
    <ul class="g-wrap">
        <li></li>
        // ...
        <li></li>
    </ul>
</ul>

改造後的 CSS:

.g-contaner {
    width: 500px;
    height: 200px;
    display: flex;
    flex-wrap: nowrap;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    overflow: auto;
}

.g-wrap {
    display: flex;
    gap: 10px;
    max-width: 100%;
}

我們通過多設置了一層 g-wrap,並且設置了 max-width: 100%,當然,它也是一個 flex 容器。

因此當:

  1. .g-wrap 內 flex item 寬度不足 100% 時,整個 .g-wrap 受到其父容器的 justify-content: center 限制會表示為水平居中;
  2. .g-wrap 內 flex item 寬度超出 100% 時,由於設置了 max-width: 100%,所以,整個容器最大寬度就是 .g-container 的寬度。此時的子 flex item 的表現就是預設的 justify-content: flex-start,因此內容也是從頭開始展示,滾動場景下沒有問題

至此,我們藉助多嵌套一層,同樣完美的解決了整個問題。其效果與方法一類似,就不再額外貼 Gif 圖。

完整的代碼,你可以戳這裡:CodePen Demo - 使用額外嵌套層解決 Flex 居中溢出問題

總結一下

好,我們快速總結一下三種方式的優劣對比:

  1. 方法一:Flex 佈局下關鍵字 safe、unsafe,修改代碼量最少,效果完美,核心問題在於相容性目前不佳;
  2. 方法二:使用 margin: auto 替代 justify-content: center,相容性好,問題在於 flex item 不足父容器 100% 時,元素之間間距無法控制;
  3. 方法三:額外嵌套一層,效果完美,改造量略多一點點。

三種方式各有優劣,基於實際面臨的業務場景再做選擇。

同時,本文舉例採用了水平方向的例子,實際在業務中,我們同樣可能會遇到垂直方向一樣的問題,本文中的解法都是通用的。並且,基於 safe 的解法中,除了 justify-content: safe center 外,safe 關鍵字還可以應用於 align-itemsalign-self,實際使用時,結合規範,選取最適合的寫法。

最後

好了,本文到此結束,希望本文對你有所幫助

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

-Advertisement-
Play Games
更多相關文章
  • HarmonyOS 開發入門(三) 日常逼逼叨 在開發入門(一)和開發入門(二)中我們描述了 HarmonyOS 開發的語言ArKTs以及Ts簡單的入門級語法操作以及開發環境的搭建,接下來我們進入第三部分:HarmonyOS基礎組件的開發,有任何說的不合理的地方,希望各位看官老爺批評指正🤣🤣 一 ...
  • 如何實現父組件監聽子組件的生命周期 方法一:$emit // 父組件 <template> <div> <Child @mounted="onMounted" @updated="onUpdated" @beforeDestroy="onBeforeDestroy" ></Child> </div> ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 背景 我司有智慧功成家APP和對應的小程式,現在已經實現APP分享到微信,微信點擊分享鏈接直接進入小程式。 目前有一個問題就是我們APP在網警那邊還沒有完全審批下來,已經搞了幾個月了,還不知道啥時能上線。微信對於這類分享是有限制的,可以分 ...
  • antd Pro組件ProFormList實現自定義action ProFormList是ant design pro的結構化數據組件,通常用來實現動態表單。 現在有個需求,除了組件自帶的刪除和複製,還需要增加兩個按鈕來實現每個item位置的上下移動,如圖所示: 查看官方文檔,組件有提供自定義act ...
  • React Zombie Child 是指在 React 組件中的一個常見問題。當一個父組件被銷毀時,它的子組件可能仍然存在於記憶體中,這些子組件被稱為“僵屍子組件”。 這種情況通常發生在非同步操作中,例如在父組件中發起了一個非同步請求,而在請求完成之前,父組件被銷毀了。但是,由於非同步請求的回調函數仍然存 ...
  • 在工作中有時候需要單獨設置某個 el-input 組件的內部樣式,比如 字體顏色、背景色、寬度、高度等,這時就需要修改 el-input 組件的內部自帶樣式,修改方式如下: 修改前: el-input 獨占滿一整行 修改後: 模板代碼 <div class="elinput"> <el-input ...
  • 廢話不多說,先看效果再上代碼 一、效果圖 二、html內容 我這裡用來外部樣式表導入css,當然你可以根據自己的喜好 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>導航欄</title> <!--導入外部樣式表--> <l ...
  • 1、業務需求 需要加一個按鈕,調用第三方API,按鈕十分鐘之內只能點擊一次,刷新頁面也只能點擊一次 2、思路 加一個本地緩存的時間戳,通過時間戳計算指定時間內不能點擊按鈕 3、實現 1)vue頁面 <template> <el-row :gutter="15"> <el-col :span="4"> ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...