作为 flexbox 的子元素的 CSS 网格未按预期运行

Posted

技术标签:

【中文标题】作为 flexbox 的子元素的 CSS 网格未按预期运行【英文标题】:CSS grid as child of flexbox not behaving as expected 【发布时间】:2018-09-12 22:14:34 【问题描述】:

我经常使用 CSS display: grid 创建一个响应式 3 列网格。我在网格中的 html 标记有 3 个 div 项,因此网格创建了 3 列

display: grid;
grid-gap: 2rem;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));

当您调整窗口大小时,它会按预期折叠为 1 列:

https://codepen.io/smlombardi/pen/oqMjrd?editors=1100

.hero-modules 
  display: grid;
  grid-gap: 2rem;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));


.hero-modules .hero-item 
  border: 1px solid #000;
  text-align: center;


.hero-modules .hero-item h3 
  font-size: 22px;
  text-align: center;
<div class="hero-modules">
  <div class="hero-item">
    <div>
      <h3>Title of Item</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
    </div>
    <div>
      <a class="hero-read-more">Read more</a>
    </div>
  </div>

  <div class="hero-item">
    <div>
      <h3>Title of Item</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
    </div>
    <div>
      <a class="hero-read-more">Read more</a>
    </div>
  </div>

  <div class="hero-item">
    <div>
      <h3>Title of Item</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
    </div>
    <div>
      <a class="hero-read-more">Read more</a>
    </div>
  </div>
</div>

现在我需要在 Flexbox 中使用这个网格,以使封闭框居中以浮动在链接背景上:

如您所见,网格折叠(添加虚线边框仅用于显示 flex 子项的范围)。

https://codepen.io/smlombardi/pen/PRBPWB?editors=1100

.hero 
  background-color: pink;
  display: flex;
  min-height: 600px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 1px solid #000;


.box 
  border: 1px dotted #000;
  text-align: center;


.button-unit 
  text-align: center;
  margin-top: 20px;


.hero-modules 
  display: grid;
  grid-gap: 2rem;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));


.hero-modules .hero-item 
  border: 1px solid #000;
  text-align: center;


.hero-modules .hero-item h3 
  font-size: 22px;
  text-align: center;
<div class="hero">
  <div class="box">
    <div>
      <h1 class="hero-heading">Check out these new features</h1>
    </div>

    <div class="hero-modules">
      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>

      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>

      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>
    </div>

    <div class="button-unit">
      <button class="btn btn-secondary mb-3">Got It</button>
      <p>
        <a class="remind-me-later" href="">Remind me later</a>
      </p>
    </div>
  </div>
</div>

<div class="container">
  <div class="row">
    <div class="col">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nostrum molestias earum beatae, minima provident sunt a et? Voluptatibus sequi ipsum ad asperiores soluta odio, nam nobis quas non totam ut officiis itaque eveniet, maiores saepe id cum consequuntur.
      Molestias suscipit quia laudantium laborum nemo ab officia, nihil esse mollitia sunt!
    </div>
  </div>
</div>

为什么会这样?有什么我遗漏的东西不允许网格正常运行吗?

【问题讨论】:

【参考方案1】:

您可以使用display: flex 属性来实现。下面是它的代码。

.hero-modules 
  display: flex;


.hero-modules .hero-item 
  flex: 1;
  margin: 10px;
  border: 1px solid #000;
  text-align: center;


.hero-modules .hero-item h3 
  font-size: 22px;
  text-align: center;
<div class="hero-modules">
  <div class="hero-item">
    <div>
      <h3>Title of Item</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
    </div>
    <div>
      <a class="hero-read-more">Read more</a>
    </div>
  </div>

  <div class="hero-item">
    <div>
      <h3>Title of Item</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
    </div>
    <div>
      <a class="hero-read-more">Read more</a>
    </div>
  </div>

  <div class="hero-item">
    <div>
      <h3>Title of Item</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
    </div>
    <div>
      <a class="hero-read-more">Read more</a>
    </div>
  </div>
</div>

【讨论】:

我知道我可以将display:grid 更改为display:flex。但我想改用网格,这个问题的目的是找出为什么网格不起作用。【参考方案2】:
Add **display:flex** property to your main container.

 .Main 
     display:flex;
  
 div 
   flex: 1;
 

然后所有 div 将充当网格以获取更多信息,请参阅下面的链接。 https://www.w3schools.com/css/css3_flexbox.asp

【讨论】:

【参考方案3】:

简单的答案:

网格容器的自动宽度基本上是它不是网格容器时的宽度。

在第一个示例中,网格容器的宽度仅受文档宽度和任何默认边距的约束。

在第二个示例中,网格容器宽度是具有默认收缩包装行为的祖先弹性项目的宽度,该行为取决于其内容的宽度,文本“Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.”(更直接地说,网格容器的宽度就是前面引用的句子的宽度。)

扩展答案:

网格容器 (.hero-modules) 具有 width: auto(默认值)。每https://drafts.csswg.org/css-grid/#grid-container:

作为块格式化上下文中的块级框,它的大小类似于建立格式化上下文的块框,自动内联大小计算为非替换块框。

在这种情况下,术语“自动内联大小”只是width: auto 的另一种说法。 (“自动内联大小”在垂直文本中为height: auto。)

“建立格式化上下文的块框”与带有display: flow-root 的框相同。将display: grid 更改为display: flow-root 将演示width: auto 的结果是使用什么宽度来计算网格容器的宽度。

所以现在我们知道了网格容器大小的来源。

flex 项目的大小来自flex-grow: 0flex-shrink: 1(默认值),这使得它的宽度缩小而不是增长。弹性项目宽度的基础是flex-basis: auto(默认),它解析为flex-basis: content。内容是文本“Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.

所以现在我们知道了 flex 项目为什么不展开以及它的宽度是基于什么的。

修复此布局

这种弹性布局不应该是基于列的;它应该是基于行的。列在唯一的弹性项目内,但不是弹性项目本身,并且需要在 x 轴而不是 y 轴上实现尺寸灵活性。

所以,flex-direction: column 需要变成 flex-direction: row

flex 布局需要增长(在 x 轴上)以适应可用空间,因此需要在 flex 项 (.box) 上指定 flex-grow: 1

最后,如果需要水平居中,grid-template-columns 值应使用auto-fit,而不是auto-fill。网格项目可以通过将justify-content: center 应用于网格容器元素来居中。

(使用auto-fill,不可见的占位符网格项将被放置以填充布局,这将导致三个当前的网格项向左对齐,并由一堆不可见的占位符项填充剩余的空白空间他们的权利。使用auto-fit,那些占位符网格项目将被简单地丢弃,并释放空间用于水平对齐。)

.hero 
  background-color: pink;
  display: flex;
  min-height: 600px;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  border: 1px solid #000;


.box 
  border: 1px dotted #000;
  flex-grow: 1;
  text-align: center;


.button-unit 
  text-align: center;
  margin-top: 20px;


.hero-modules 
  display: grid;
  grid-gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  justify-content: center;


.hero-modules .hero-item 
  border: 1px solid #000;
  text-align: center;


.hero-modules .hero-item h3 
  font-size: 22px;
  text-align: center;
<div class="hero">
  <div class="box">
    <div>
      <h1 class="hero-heading">Check out these new features</h1>
    </div>

    <div class="hero-modules">
      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>

      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>

      <div class="hero-item">
        <div>
          <h3>Title of Item</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dicta est ipsa recusandae.</p>
        </div>
        <div>
          <a class="hero-read-more">Read more</a>
        </div>
      </div>
    </div>

    <div class="button-unit">
      <button class="btn btn-secondary mb-3">Got It</button>
      <p>
        <a class="remind-me-later" href="">Remind me later</a>
      </p>
    </div>
  </div>
</div>

<div class="container">
  <div class="row">
    <div class="col">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nostrum molestias earum beatae, minima provident sunt a et? Voluptatibus sequi ipsum ad asperiores soluta odio, nam nobis quas non totam ut officiis itaque eveniet, maiores saepe id cum consequuntur.
      Molestias suscipit quia laudantium laborum nemo ab officia, nihil esse mollitia sunt!
    </div>
  </div>
</div>

【讨论】:

您建议的布局修复不符合相关要求。 OP 希望网格项目根据可用大小在一行或一列中对齐。这是问题的屏幕截图prntscr.com/j470a2 我使用的是 Chrome 65,Windows 10 @VadimOvchinnikov 您是使用“整页”视图还是仅使用屏幕截图中显示的小预览框? (在单击“运行代码 sn-p”之前,“整页”按钮不可见。)演示代码在 Linux Mint 18 上的 Chromium 65 中对我来说工作正常。值得注意的是,OP 的第一个第二个示例考虑到屏幕截图中显示的布局的可能性,给定的视口宽度只能容纳两列。 尽管我不完全同意您的回答,但我很欣赏它所显示的工作量。另外,sn-p 对我来说似乎工作正常

以上是关于作为 flexbox 的子元素的 CSS 网格未按预期运行的主要内容,如果未能解决你的问题,请参考以下文章

使用 CSS Grid 和 Flexbox 水平对齐位于不同网格单元格中的元素

CSS Flexbox:居中的子元素溢出位置固定的父元素

如何在更改后的Flexbox网格中获取Vue元素的更新CSS宽度?

CSS Flexbox - 相对于父元素居中所有具有全高的子元素[重复]

使用 flexbox 具有相同高度元素的多线网格

带有 flexbox 的 css 正方形网格