自动剪裁多行 flexbox

Posted

技术标签:

【中文标题】自动剪裁多行 flexbox【英文标题】:Autoclipping multi-line 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 的一部分。 【参考方案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;
  

等其他人...

【讨论】:

对不起,我特意问了一句“没有媒体查询怎么办?”。

以上是关于自动剪裁多行 flexbox的主要内容,如果未能解决你的问题,请参考以下文章

按钮文本被剪裁,自动布局,ios

Flexbox布局

Wes7 剪裁方法

Google开源框架AutoFlip 实现视频智能剪裁

coreldraw怎样把一段文字自动放入图框内

带有多个内衬标签的estimatedRowHeight 导致单元格剪裁