搜索

首页  >  问答  >  正文

如何使用flexbox实现这种响应式布局

我正在制作一个 React 应用程序,它在 Flex 容器内呈现 xy 数量的卡片和单个小部件。所有卡片具有相同的宽度和高度,但小部件的高度等于卡片高度 * 2 + row-gap。容器的宽度根据视口宽度而变化,并且在视觉上应分别看起来为带有卡片的 2 或 3 列。为了进一步清晰起见,我提供了所需布局的模型图像,小部件用蓝色表示。

无论我尝试什么,如果不将行的高度更改为其大小,我都无法让小部件显示在正确的位置,从而留下一个“空白行”,其中应该呈现 1 或 2 个以上的卡片,如显示在下图。

我当前的解决方案涉及 Javascript,根据视口宽度,我将 2 或 4 张卡加载到一个单独的小 Flex 容器中,该容器被渲染为主 Flex 容器的第一个子容器。这种解决方法在视觉上效果很好,但使我的代码变得更加复杂,因为我必须涵盖许多不同的情况才能使其正常运行。我想使用 css/flexbox 实现同样的目标,但我仍然是一个初学者,以前从未做过这样的布局,显然不知道如何做到这一点。小部件无法绝对定位,因为这会破坏其子元素的滚动功能。

我正在以正确的比例提供测试 HTML 和 CSS 测量值,以防有帮助。

.container {
  margin: 50px 300px;
  display: flex;
  flex-wrap: wrap;
  row-gap: 20px;
  column-gap: 20px;
  min-width: 320px; /* Width for 2 columns */
  max-width: 490px; /* Width for 3 columns */
  border: 3px solid rgb(0, 22, 117);
}

.card {
  width: 150px;
  height: 100px;
  background-color: bisque;
}

.widget {
  height: 220px; /* card height * 2 + row-gap */
  width: 150px;
  background-color: rgb(134, 204, 245);
}
<div class="container">
  <div class="widget"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>

<!-- Original jsx
<div className='container'>
  <div className='widget'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
  <div className='card'></div>
</div>
-->

我真的很想学习如何在 Flexbox 中创建这样的布局,不仅是因为我当前的项目,而且也是为了扩展我的知识和理解。如果您对如何解决这个问题有任何想法,请帮助我。预先感谢您:)

P粉733166744P粉733166744348 天前458

全部回复(2)我来回复

  • P粉391677921

    P粉3916779212024-02-27 15:38:05

    这可以使用网格布局来完成,无需 JavaScript,下面是一个示例:

    .container {
      margin: 50px 300px;
      display: grid;
      /* auto calculate columns, minimun cell width is 140px */  
      grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
      
      /* height of each cell */
      grid-auto-rows: 100px;
      
      grid-auto-flow: row dense;
      gap: 20px;
      min-width: 320px;
      max-width: 490px;
      border: 3px solid rgb(0, 22, 117);
    }
    
    .card {
      background-color: bisque;
    }
    
    .widget {
      background-color: rgb(134, 204, 245);
      /* widget, span for 2 rows */
      grid-row: auto / span 2;
      
      /* set the widget to the right most column */
      grid-column-end: -1;
    }
    <div class="container">
      <div class="widget"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
    </div>
    
    <!-- Original jsx
    <div className='container'>
      <div className='widget'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
      <div className='card'></div>
    </div>
    -->

    正如@ralph.m 提到的。您始终可以通过将 grid-column-end: -1; 设置为 .widget.widget >

    回复
    0
  • P粉321584263

    P粉3215842632024-02-27 09:10:49

    Flexbox 布局无法做到这一点,它不会创建 2d 网格,您必须使用 gridbox 布局。,因此元素可以跨越行和列而不留间隙。< /p>

    这是一个例子:

    .grid {
    /* give some space gutters */
      margin: 1em auto;
      padding:1em;
      gap: 1em;
     /* build a grid */
      display: grid; 
      grid-auto-flow: row dense;/* fill any holes that could show up */
      grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); /* auto calculate size of the grid */
      grid-auto-rows: 75px; /* give an height row for the demo */
      max-width: 80%;/* whatever */
      border: solid;/* see my boundaries */
    }
    
    .card {
      background-color: salmon;
    }
    
    .bigger {
      background-color: lightblue;
      grid-row: 1/ span 2;/* keep me on first row and lay over 2 rows */
      grid-column-end: -1; /* keep me on the last column no matter how many */
    }
    <div class="grid">
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="bigger">I can be anywhere in the flow but I'll show on top end</div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>  
    </div>

    回复
    0
  • 取消回复