【佈局技巧】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 微服務框架,幫助我們輕鬆構建和管理微服務應用。 本框架不僅支持 Consul 服務註 ...
  • 先看一下效果吧: 如果不會寫動畫或者懶得寫動畫,就直接交給Blend來做吧; 其實Blend操作起來很簡單,有點類似於在操作PS,我們只需要設置關鍵幀,滑鼠點來點去就可以了,Blend會自動幫我們生成我們想要的動畫效果. 第一步:要創建一個空的WPF項目 第二步:右鍵我們的項目,在最下方有一個,在B ...
  • Prism:框架介紹與安裝 什麼是Prism? Prism是一個用於在 WPF、Xamarin Form、Uno 平臺和 WinUI 中構建鬆散耦合、可維護和可測試的 XAML 應用程式框架 Github https://github.com/PrismLibrary/Prism NuGet htt ...
  • 在WPF中,屏幕上的所有內容,都是通過畫筆(Brush)畫上去的。如按鈕的背景色,邊框,文本框的前景和形狀填充。藉助畫筆,可以繪製頁面上的所有UI對象。不同畫筆具有不同類型的輸出( 如:某些畫筆使用純色繪製區域,其他畫筆使用漸變、圖案、圖像或繪圖)。 ...
  • 前言 嗨,大家好!推薦一個基於 .NET 8 的高併發微服務電商系統,涵蓋了商品、訂單、會員、服務、財務等50多種實用功能。 項目不僅使用了 .NET 8 的最新特性,還集成了AutoFac、DotLiquid、HangFire、Nlog、Jwt、LayUIAdmin、SqlSugar、MySQL、 ...
  • 本文主要介紹攝像頭(相機)如何採集數據,用於類似攝像頭本地顯示軟體,以及流媒體數據傳輸場景如傳屏、視訊會議等。 攝像頭採集有多種方案,如AForge.NET、WPFMediaKit、OpenCvSharp、EmguCv、DirectShow.NET、MediaCaptre(UWP),網上一些文章以及 ...
  • 前言 Seal-Report 是一款.NET 開源報表工具,擁有 1.4K Star。它提供了一個完整的框架,使用 C# 編寫,最新的版本採用的是 .NET 8.0 。 它能夠高效地從各種資料庫或 NoSQL 數據源生成日常報表,並支持執行複雜的報表任務。 其簡單易用的安裝過程和直觀的設計界面,我們 ...
  • 背景需求: 系統需要對接到XXX官方的API,但因此官方對接以及管理都十分嚴格。而本人部門的系統中包含諸多子系統,系統間為了穩定,程式間多數固定Token+特殊驗證進行調用,且後期還要提供給其他兄弟部門系統共同調用。 原則上:每套系統都必須單獨接入到官方,但官方的接入複雜,還要官方指定機構認證的證書 ...
  • 本文介紹下電腦設備關機的情況下如何通過網路喚醒設備,之前電源S狀態 電腦Power電源狀態- 唐宋元明清2188 - 博客園 (cnblogs.com) 有介紹過遠程喚醒設備,後面這倆天瞭解多了點所以單獨加個隨筆 設備關機的情況下,使用網路喚醒的前提條件: 1. 被喚醒設備需要支持這WakeOnL ...
  • 前言 大家好,推薦一個.NET 8.0 為核心,結合前端 Vue 框架,實現了前後端完全分離的設計理念。它不僅提供了強大的基礎功能支持,如許可權管理、代碼生成器等,還通過採用主流技術和最佳實踐,顯著降低了開發難度,加快了項目交付速度。 如果你需要一個高效的開發解決方案,本框架能幫助大家輕鬆應對挑戰,實 ...