【问题标题】:Autoclipping multi-line flexbox自动剪裁多行 flexbox
【发布时间】:2022-01-22 21:51:08
【问题描述】:

我需要在一张漂亮的表格中展示 8-9 张卡片,每行有 2-4 行和 2-4 个元素。所有行都有相同数量的元素。

即根据容器元素的宽度,用户应该看到以太 8 或 9 卡:

C1 C2 C3 C4
C5 C6 C7 C8

C1 C2 C3
C4 C5 C6
C7 C8 C9

C1 C2
C3 C4
C5 C6
C7 C8

如果没有媒体查询,我该怎么做?

最自然的方式似乎是带有flex-wrap: wrap 的flexbox,但是如何解释flexbox 如果它只包含一个元素,我需要隐藏一行?有只有css的解决方案吗?我可以用 javascript 检测一个包装的 flexbox 有多少行吗?

【问题讨论】:

  • 媒体查询有什么问题,它们是响应式设计的基本组件/
  • @Paulie_D,媒体查询将无法预测,因为 flexbox 容器可以占据页面的任意部分。您在这里需要容器查询,而不是媒体查询,但容器查询不是当前 CSS 的一部分。

标签: css flexbox


【解决方案1】:

Flexbox 结合flex-wrap: wrap 和媒体查询可以是一个很好的解决方案。

您可以设置多个断点并为不同的屏幕尺寸创建不同的行为。这可以是(除了设置flex-basis)也可以用display: none隐藏最后一个元素

使用移动优先的方法,您可以这样做:

.wrapper {
  display: flex;
  flex-wrap: wrap;
}
.wrapper div {
  flex-basis: 50%;
}
.wrapper div:last-child {
  display: none;
}
@media (min-width: 600px) {
  .wrapper div {
    flex-basis: 33.33%;
  }
  .wrapper div:last-child {
    display: block;
  }
}
@media (min-width: 992px) {
  .wrapper div {
    flex-basis: 25%;
  }
  .wrapper div:last-child {
    display: none;
  }
}
<div class="wrapper">
  <div>C1</div>
  <div>C2</div>
  <div>C3</div>
  <div>C4</div>
  <div>C5</div>
  <div>C6</div>
  <div>C7</div>
  <div>C8</div>
  <div>C9</div>
</div>

【讨论】:

  • 太棒了。这是艺术
  • 很抱歉,我特意问了一句“没有媒体查询我该怎么做?”。如果您的包装器占用页面的任意部分,媒体查询将无法正常工作。
  • 对不起,我被错字弄糊涂了(“没有”是一起写的)......无论如何我不知道你的确切实现,但是使用MQ你也可以控制包装器的宽度(取决于视口宽度)并确保它按预期工作。这还不够吗?
  • @TomasKorinek,你是什么意思?我需要我的容器元素是它们已经是的宽度,独立于它们的内部内容,包括表格的这个解决方案。 Card table 必须完全适合我放入的元素,并且这些元素的宽度和它对媒体查询的依赖已经确定。
  • 再来一次:卡表布局必须依赖于包含卡表的元素的宽度,而不是页面的宽度。这就是我要解决的问题。
【解决方案2】:

最好的办法是使用容器查询,但不幸的是,到 2021 年它们现在还没有得到广泛支持。除此之外,我不知道没有媒体查询的这个确切问题的纯 CSS 解决方案。

我仍然相信媒体查询是一个很好的解决方案(如果您能够找到视口宽度和容器宽度之间的关系),但由于您坚持不使用它们,您唯一的方法是使用一些 javascript (虽然布局依赖于 JS 可能不是一个好主意)。

一种方法是使用已经制作的库之一(例如EQCSS),但如果您想拥有自己的解决方案,您可以模拟容器查询,例如这样。

$(function() {
  updateWrapper(); // call on page load
  $(window).on('resize', function(){
    updateWrapper(); // update on window resize
  });
});

function updateWrapper() {
  var innerWrapper = $('.wrapper > div'); // get inner wrapper
  innerWrapper.removeClass(); // remove previously set class

  var elWidth = $('.wrapper').width(); // get container width
  if(elWidth < 600) { // set class according to container width
    innerWrapper.addClass('mobile');
  } else if (elWidth >= 600 && elWidth < 992) {
    innerWrapper.addClass('tablet');
  } else {
    innerWrapper.addClass('desktop');
  }
}
.wrapper {
  /* width: 400px; // use any value here */
  background: lightgray;
}
.wrapper > div {
  display: flex;
  flex-wrap: wrap;
}

.mobile div {
  flex-basis: 50%;
}
.mobile div:last-child {
  display: none;
}

.tablet div {
  flex-basis: 33.33%;
}
.tablet div:last-child {
  display: block;
}

.desktop div {
  flex-basis: 25%;
}
.desktop div:last-child {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
  <div>
    <div>C1</div>
    <div>C2</div>
    <div>C3</div>
    <div>C4</div>
    <div>C5</div>
    <div>C6</div>
    <div>C7</div>
    <div>C8</div>
    <div>C9</div>
  </div>
</div>

【讨论】:

    【解决方案3】:

    由于您决定在 JavaScrpt 中观察行数,因此使用 javascript 很容易完成布局(无论如何,您最终将使用 JavaScript,所以我认为这不值得一笑)。 如果没有,则使用媒体查询来控制元素的显示,并使用 grid 代替 flexbox,这样:

    文档结构:

    .container
      #card1.card
      #card2.card
      ...
      #card8.card
      #card9.card
    
    .container{
      display: grid;
      grid-template: 1fr 1fr 1fr / 1fr 1fr 1fr;
    }
    @media all and (min-width: 600px){
      .container{
        grid-template: 1fr 1fr 1fr 1fr / 1fr 1fr;
      }
      .card:last-child{
        display: none;
      }
    }
    

    等其他人...

    【讨论】:

    • 对不起,我特意问了一句“没有媒体查询怎么办?”。
    猜你喜欢
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    相关资源
    最近更新 更多