响应式 flexbox 和重新排序子子项

Posted

技术标签:

【中文标题】响应式 flexbox 和重新排序子子项【英文标题】:Responsive flexbox and reordering subchildren 【发布时间】:2020-05-16 18:14:21 【问题描述】:

我需要一些关于响应式 html 的帮助。

我有一个 flexbox 布局,有两列。每列包含两个不同高度的 div。

在移动设备上,我将 flex-direction 设置为列,因此它分成一列:

但正如您可能已经猜到的那样,我希望订单是 ABCD。我意识到我目前的设置可能无法做到这一点,因为 AFAIK 你不能订购子孩子。但是我有什么选择来获得想要的结果?

我可以用 javascript 重新排列东西,但如果可能的话,我更喜欢纯 CSS 方法。

这可以实现吗?我需要 CSS 网格来执行此操作吗?

我添加了一个 sn-p 来说明这个问题。也在codepen上:https://codepen.io/Mudloop/pen/PowrKPV

(为简单起见,它没有媒体查询,只是相同的 html 两次不同的类)。

*  box-sizing: border-box; 
body  background-color: #444; color: white; font-family: sans-serif; max-width:650px; 

.normal 
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  margin: 20px;

.normal > div 
  color: white;
  width: calc(50%);

.normal > div > div 
  background-color: #333;
  padding: 10px;
  margin: 10px;



.mobile 
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-items: flex-start;
  margin:20px;


.mobile > div 
  color: white;
  width: 100%;

.mobile > div > div 
  background-color: #333;
  padding: 10px;
  margin: 10px;
<body>
  Desktop
  <div class="normal">
    <div>
      <div>A<br></div>
      <div>C<br><br><br><br><br></div>
    </div>
    <div>
      <div>B<br><br></div>
      <div>D<br><br><br></div>
    </div>
  </div>

  Mobile
  <div class="mobile">
    <div>
      <div>A<br></div>
      <div>C<br><br><br><br><br></div>
    </div>
    <div>
      <div>B<br><br></div>
      <div>D<br><br><br></div>
    </div>
  </div>
</body>

【问题讨论】:

grid 肯定会用 css order property 解决它。 谢谢@RicoKahler。我希望有另一种解决方案,因为 CSS 网格让我害怕 :) 但如果没有,我会尝试找出它们。 看起来 CSS 网格也不能解决问题,因为网格单元格不能具有可变(任意)高度。 【参考方案1】:

您可以在桌面上使用multi-column 布局。 并在移动设备上使用媒体查询切换到flex(允许重新order 元素)。

Full page模式下运行下面的例子并尝试调整窗口大小: (我在块中添加了一些文本以使它们更真实)

* 
  box-sizing: border-box;


body 
  background-color: #444;
  color: white;
  font-family: sans-serif;
  max-width: 1280px;
  width: 100%


.normal 
  padding: 10px;
  border: solid 1px #ccc;
  margin: 20px;
  columns: 2 200px;
  column-fill: balance;


.normal>div 
  margin: 0 0 10px;
  padding: 10px;
  background-color: #333;
  page-break-inside: avoid;


@media (max-width:480px) 
  .normal 
    display: flex;
    flex-direction: column
  
  .normal>div:nth-child(1) 
    order: 1
  
  .normal>div:nth-child(2) 
    order: 3
  
  .normal>div:nth-child(3) 
    order: 2
  
  .normal>div:nth-child(4) 
    order: 4
  
Desktop
<div class="normal">
  <div>A<br>Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs.</div>
  <div>C<br>The purpose of lorem ipsum is to create a natural looking block of text (sentence, paragraph, page, etc.) that doesn't distract from the layout. A practice not without controversy, laying out pages with meaningless filler text can be very useful
    when the focus is meant to be on design, not content.</div>
  <div>B<br>It usually begins with:<br>“Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.”</div>
  <div>D<br> The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De Finibus Bonorum et Malorum for use in a type specimen book.</div>
</div>

【讨论】:

这看起来是一个很好的解决方案。以前从未听说过多列布局,很高兴知道它的存在。而且它似乎得到了很好的支持。 @SvenM,很乐意为您提供帮助。 似乎如果单元格 A 变大,它会将单元格 C 推到下一列。你知道有没有办法解决这个问题? (无论内容如何,​​我的布局都保持一致)。 设法通过将 column-fill 设置为 auto 并添加 break-after:avoid 和 break-after:column 来解决它(我认为)。【参考方案2】:

是的,您可以通过在具有display: flex 的容器内的子项上使用order 属性来实现此目的,并结合媒体查询,而无需使用网格。我不确定您的布局对 HTML 结构的约束是什么,所以我对其进行了一些更改。

我为“桌面”布局使用了最大高度来强制弹性项目用列流包装。然后,当媒体查询被触发时(您可以将其设置为您支持的任何移动设备尺寸),最大高度被删除,并且里面的项目可以根据您指定的order 属性将它们自己设置在一个列中。

您可以将其放入代码笔中,调整窗口大小,它应该可以工作。

<body>
  Desktop
  <div class="normal">
      <div id="a">A<br></div>
      <div id="c">C<br><br><br><br><br></div>
      <div id="b">B<br><br></div>
      <div id="d">D<br><br><br>
    </div>
  </div>

*  box-sizing: border-box; 
body  background-color: #444; color: white; font-family: sans-serif;  

.normal 
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-items: flex-start;
  margin: 20px;
  max-height: 200px;

.normal > div 
  color: white;
  width: calc(50%);

.normal > div 
  background-color: #333;
  padding: 10px;
  margin: 10px;


@media (max-width: 500px) 

  .normal 
    display: flex;
    flex-direction: column;
    flex-wrap: none;
    align-items: center;
    max-height: none;
  

  #a 
    order: 1
  

  #b 
    order: 2
  

  #c 
    order: 3
  

  #d 
    order: 4
  


【讨论】:

谢谢,但问题是我不知道最大高度。这些列显示用户生成的内容,所以我不能硬编码高度约束。但是,我也许可以用 javascript 计算最大高度。我更喜欢纯 CSS,但看起来我需要一些 javascript 来解决这个或另一种方式。

以上是关于响应式 flexbox 和重新排序子子项的主要内容,如果未能解决你的问题,请参考以下文章

CSS Flexbox 响应式布局和 % 宽度

使用 Twitter Bootstrap 响应式地重新排序 div?

如何使 flexbox 响应式?

使用 flexbox 的响应式投资组合/联系人

具有动态内容的 Flexbox 响应式超级菜单

网格项高度与响应式方形子项不匹配