七夏 发表于 2025-2-3 17:26:07

CSS如何优雅的实现卡片多行排列布局?

<h1>需求简介</h1>
<p>在前端开发中,我们经常遇见这样的开发需求,实现下列以此排布的卡片,这些卡片宽度一般是固定的,</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7lcwft00vfUdRUEEUOefT5iajn7UHNmBRYDSqd9eMorboKUcyibdTEW4FQ/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" /></p>
<p>并且在不同大小的屏幕宽度下自动换行。</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7lobAvmpW0CFdFRtOhukYFFxS8oK3eL0CSBN6PSP99iakgUbDMgAMY8NQ/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" /></p>
<h1>实际开发中遇到的问题</h1>
<p>实现这样的一个需求其实不难,我们很容易想到设置一个安全宽度(如下图绿色),然后进行弹性布局。</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7l6f99ibymSqOics23qe2CYhk41z7gsqMUSaqvLAaUyDAdUDnCe9KzplZw/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" /></p>
<p>一个很容易写出的代码是这样的:</p>
<pre><code>&lt;template&gt;
  &lt;div class=&quot;container&quot;&gt;
    &lt;div class=&quot;crad&quot;&gt;1&lt;/div&gt;
    &lt;div class=&quot;crad&quot;&gt;2&lt;/div&gt;
    &lt;div class=&quot;crad&quot;&gt;3&lt;/div&gt;
    &lt;div class=&quot;crad&quot;&gt;4&lt;/div&gt;
    &lt;div class=&quot;crad&quot;&gt;5&lt;/div&gt;
    &lt;div class=&quot;crad&quot;&gt;6&lt;/div&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;style lang=&quot;less&quot; scoped&gt;
.container{
  width:630px;
  display: flex;
  justify-content: space-between;
  flex-flow: wrap;
  .crad{
    height:100px;
    background: blueviolet;
    width:200px;
    margin-bottom: 16px;
  }
}
&lt;/style&gt;
</code></pre>
<p>使用flex弹性布局,我们很看似轻松的实现了需求。但是,当我们将卡片数量减少一个,问题就出现了</p>
<pre><code>&lt;template&gt;
&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;crad&quot;&gt;1&lt;/div&gt;
  &lt;div class=&quot;crad&quot;&gt;2&lt;/div&gt;
  &lt;div class=&quot;crad&quot;&gt;3&lt;/div&gt;
  &lt;div class=&quot;crad&quot;&gt;4&lt;/div&gt;
  &lt;div class=&quot;crad&quot;&gt;5&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;
</code></pre>
<p>由于我们使用了 <code>justify-content: space-between</code>;的布局方式,4,5卡片左右对称布局,这显然不符合我们的要求!</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7l1hlOKicnr90xSicKNU4gUXHZlX1NGfcyNWtkcYVOGJibY6ZT0egqx0a2g/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" /></p>
<p>聪明的人,可能会把 <code>justify-content: space-between</code>改成 <code>align-content: space-between</code></p>
<pre><code>&lt;style lang=&quot;less&quot; scoped&gt;
.container{
  width:630px;
  display: flex;
  align-content: space-between;
  flex-flow: wrap;
  .crad{
    height:100px;
    background: blueviolet;
    width:200px;
    margin-bottom: 16px;
  }
}
&lt;/style&gt;
</code></pre>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7lw3MTBU5kkycOwozAicxOOaHWgjg03picurEm5eKadHDkjWzm0DPSccTQ/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" /></p>
<p>这样的确会让卡片以此排列,但是没了右边距!因此,你可能会手动加上右边距</p>
<pre><code>&lt;style lang=&quot;less&quot; scoped&gt;
.container{
  width:630px;
  display: flex;
  align-content: space-between;
  flex-flow: wrap;
  .crad{
    height:100px;
    background: blueviolet;
    width:200px;
    margin-bottom: 16px;
    margin-right: 16px;
  }
}
&lt;/style&gt;
</code></pre>
<p>你会尴尬的发现换行了,因为两个卡片的宽度加元素的右边距之和大于你设置的安全宽度了!</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7lVNOWndMRSFg90S7SEhQicqTmicV17Pj7QMNVH5P4qAIianow1x9SviarPw/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" /></p>
<p>当然,你可以让每个卡片的右边距小一点,这样不会换行,但是,右边的元素永远无法贴边了!</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7lniaQMYbWlpdVR19v4neCqwZWSNV5j9xic2VQFtMVRU7ZhPDhOnZds7Iw/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" /></p>
<h1>如何解决这个问题</h1>
<p>想解决上的问题,也有很多方法。</p>
<p>如果永远是第3n的元素是最后一列,这个问题非常容易解决:</p>
<pre><code>.container{
  display: flex;
  width:630px;
  align-content: space-between;
  flex-flow: wrap;
  .crad{
    height:100px;
    background: blueviolet;
    width:200px;
    margin-bottom: 16px;
    margin-right: 16px;
    &amp;:nth-child(3n) {
      margin-right: 0;
    }
  }
}
</code></pre>
<p>4n,5n,6n我们都可以用这样的方式解决!</p>
<p>但如果安全宽度是变化的(630px不固定),比如随着浏览器尺寸的变化,每行的卡片数量也变化,上述方式就无法解决了。</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_gif/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7lsA4Es5nLd8lqsnicebj2W4vwicibhomjAFPmMicrz2GSZZtk3bfpOI4VEw/640?wx_fmt=gif&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1" alt="图片" /></p>
<p>此时,我们可以用下面的方法:</p>
<p>我们可以在绿色盒子外在套一个红色盒子,超出红色盒子的部分隐藏即可<img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7lU35897MKr3vcKb8IQxOj9g6Pv8ciaY7g7DCKdk0gh1ib48OrdIdUJJHw/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" /></p>
<p>代码如下</p>
<pre><code>&lt;template&gt;
  &lt;div class=&quot;card-content-box&quot;&gt;
    &lt;div class=&quot;container&quot;&gt;
        &lt;div class=&quot;crad&quot;&gt;1&lt;/div&gt;
        &lt;div class=&quot;crad&quot;&gt;2&lt;/div&gt;
        &lt;div class=&quot;crad&quot;&gt;3&lt;/div&gt;
        &lt;div class=&quot;crad&quot;&gt;4&lt;/div&gt;
        &lt;div class=&quot;crad&quot;&gt;5&lt;/div&gt;
   &lt;/div&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;style lang=&quot;less&quot; scoped&gt;
.card-content-box{
    width:100%;
    background:red;
    overflow: hidden;
    .container{
      width: calc(100% + 16px);
      display: flex;
      align-content: space-between;
      flex-flow: wrap;
      .crad{
        height:100px;
        background: blueviolet;
        width:200px;
# margin-bottom: 16px;
      }
    }
}
&lt;/style&gt;
</code></pre>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibtpIU093Rdg4mMHrXqhRm7lVdvHSspDyic8wM8hGeGdgvG6WSUBJQbBlCAZ8gDPCwKt9NZwtW4L0Og/640?wx_fmt=png&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" /></p>
<p>上述代码中,我们的container元素设置了 <code>width: calc(100% + 16px)</code>保证其比父元素多出16px的容错边距,然后我们给红色盒子设置了 <code>overflow: hidden</code>,就避免了滚动条出现。</p>
<p>完美解决了这个布局问题!</p>
页: [1]
查看完整版本: CSS如何优雅的实现卡片多行排列布局?