【佈局技巧】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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...