彈性盒佈局之從左往右,空間不夠換行繼續從左往右(從左往右,從上往下,between效果)

水冗水孚發表於2023-02-17
本文記錄一個css小技巧,不難,不過可能自己一時間想不到

問題描述

我們有這樣的需求,大容器中有很多的盒子,從左往右排列,空間不夠的話,然後換行,繼續從左往右排列,如下效果圖

看到這樣的需求,我們第一時間想到的就是彈性盒佈局,給大容器開啟彈性盒、允許換行,兩側分佈,於是會寫下如下程式碼:

display: flex;
flex-wrap: wrap;
justify-content: space-between;

如果是正好9個項,那這種寫法沒有問題,如果是8個項,最後一行的7和8就會兩側分佈了,如下圖:

這種效果肯定不行啊,那怎麼辦呢?

解決方案一 使用真實DOM進行填充,然後再隱藏這個DOM

  • 我們再建立一個dom元素項,作為最後一個9
  • 然後把第9項的高度置為0,只保留寬度
  • 或者再加點透明度為0障眼法使其看不到即可

程式碼如下(複製貼上使用):

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .wrap {
            width: 480px;
            height: 360px;
            border: 4px solid #000;
            overflow-y: auto;
            box-sizing: border-box;
            padding: 6px;
            /* 開啟彈性盒,換行,兩端分佈 */
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
        }

        .item {
            width: 120px;
            height: 120px;
            line-height: 120px;
            text-align: center;
            border: 2px solid pink;
            font-weight: 700;
            font-size: 24px;
            margin-bottom: 8px;
            /* 注意是border-box盒模型 */
            box-sizing: border-box;
        }

        /* 障眼法佔位項 */
        .fakeItem {
            width: 120px;
            height: 0;
            border: 2px solid green;
            box-sizing: border-box;
            opacity: 0;
            /* visibility: hidden; */
        }
    </style>
</head>

<body>
    <div class="wrap">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
    </div>
    <script>
        /**
         * 透過js新增一個假的項,即為佔位項
         * 佔位項的高度為0,寬度和其他項寬度一樣
         * 也可加透明度為0,或者visibility都行的
         * 只要障眼法看不到即可
         * */
        let wrap = document.querySelector('.wrap')
        let divDom = document.createElement('div')
        divDom.classList.add('fakeItem')
        wrap.appendChild(divDom)
    </script>
</body>

</html>

這樣就實現了,本文中的第一個效果圖

解決方案二 使用偽元素在最後位置進行填充

建立dom,渲染dom有些耗費效能(實際上肉眼看不出區別的),那我們就不建立dom唄,直接使用偽元素模擬一個真實的dom,思路基本一致的,於是,我們就有了以下“最佳化”程式碼

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .wrap {
            width: 480px;
            height: 360px;
            border: 4px solid #000;
            overflow-y: auto;
            box-sizing: border-box;
            padding: 6px;
            /* 開啟彈性盒,換行,兩端分佈 */
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
        }

        /* 解決最後一行不從左往右排布問題 */
        .wrap::after {
            content: "";
            height: 0;
            /* 和內容項的寬度保持一致 */
            width: 120px;
        }

        .item {
            width: 120px;
            height: 120px;
            line-height: 120px;
            text-align: center;
            border: 2px solid pink;
            font-weight: 700;
            font-size: 24px;
            margin-bottom: 8px;
            /* 注意是border-box盒模型 */
            box-sizing: border-box;
        }
    </style>
</head>

<body>
    <div class="wrap">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <!-- <div class="item">9</div> -->
    </div>
</body>

</html>

擴充柵格佈局也是一種思路

另外也可以使用柵格佈局的方式進行嘗試

柵格佈局非常強大哦!!!

擴充思路程式碼

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .grid-box {
            display: grid;
            grid-template-columns: auto auto auto;
            border: 1px solid #333;
        }

        .grid-box-item {
            font-size: 30px;
            text-align: center;
            padding: 12px;
            border-right: 1px solid #333;
            border-bottom: 1px solid #333;
        }

        .grid-box-item:last-child {
            border-bottom: none;
        }

        .grid-box-item:nth-last-child(2) {
            border-bottom: none;
        }

        .grid-box-item:nth-child(3n) {
            border-right: none;
        }
    </style>
</head>

<body>
    <div class="grid-box">
        <div class="grid-box-item">1</div>
        <div class="grid-box-item">2</div>
        <div class="grid-box-item">3</div>
        <div class="grid-box-item">4</div>
        <div class="grid-box-item">5</div>
        <div class="grid-box-item">6</div>
        <div class="grid-box-item">7</div>
        <div class="grid-box-item">8</div>
    </div>
</body>

</html>

相關文章