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

CSS grid as child of flexbox not behaving as expected

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

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

当您调整 window 大小时,它会按预期折叠成 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 中使用这个网格,使封闭框居中浮动在 link 背景上:

如您所见,网格折叠(添加虚线边框只是为了显示 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>

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

简单答案:

如果网格容器不是网格容器,网格容器的自动宽度基本上就是它的宽度。

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

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

扩展答案:

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

As a block-level box in a block formatting context, it is sized like a block box that establishes a formatting context, with an auto inline size calculated as for non-replaced block boxes.

术语 "auto inline size" 只是 width: auto 在这种情况下的另一种说法。 ("auto inline size" 在竖排文本中是 height: auto。)

"A block box that establishes a formatting context"等同于带display: flow-root的方框。将 display: grid 更改为 display: flow-root 将演示使用什么宽度来计算网格容器的宽度作为 width: auto.

的结果

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

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

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

修复此布局:

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

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

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

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

(使用auto-fill,将放置不可见的占位符网格项来填充布局,这将导致当前的三个网格项向左对齐,并用一堆不可见的占位符项填充在他们的右边保持空白 space。使用 auto-fit,那些占位符网格项目被简单地丢弃并且 space 被释放用于水平对齐。)

.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>

Add **display:flex** property to your main container.

 .Main {
     display:flex;
  }
 div {
   flex: 1;
 }

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

您可以使用 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>