首页 > 解决方案 > 如何使用 flex/grid 在容器中居中网格?

问题描述

尽管有很多关于 div 居中的问题,但由于某种原因,它们似乎都不起作用。作为我使用 flex/grid 的 css noob,我所知道的是我想要拥有:


    <div className="flex flex-col h-screen">
      <!-- HEADER -->
      <header className="flex h-20 bg-gray-100 justify-center items-center">
        <span className="font-bold text-2xl">
          title
        </span>
      </header>
    
      <!-- BODY -->
      <div className="flex-1 flex-col mx-auto justify-center items-center max-w-screen-lge p-5">
        <div className="grid grid-cols-2 gap-4 items-center">
          <div className="flex col-span-1 h-20 items-center justify-center bg-gray-300">
            1
          </div>
          <div className="flex col-span-1 h-20 justify-end bg-gray-300">
            2
          </div>
          <div className="flex col-span-2 h-12 items-center justify-center bg-gray-300">
           3
          </div>
          <div className="flex col-span-2 h-48 items-center justify-center bg-gray-300">
            4
          </div>
          <div className="flex col-span-2 h-48 items-center justify-center bg-gray-300">
            5
          </div>
        </div>
      </div>
    
      <!-- FOOTER -->
      <footer className="flex h-20 bg-gray-100 justify-center items-center">
        <p>footer text</p>  
      </footer>
    </div>

到目前为止,它看起来像这样: 布局

我如何将网格 div 居中在 flex-1 (这甚至是正确的选择吗?)容器中?

编辑: 父元素 内容(子)

标签: htmlcssflexboxtailwind-css

解决方案


不知道你如何在顺风中做到这一点,但这里有一个最小的例子,说明你如何用普通的 css 做到这一点。

我没有以任何结构方式更改您的标记。刚刚删除了类名,以便更轻松地查看影响了什么。

这在微小的堆栈溢出片段窗口中以一种不受欢迎的方式被挤压(您可能需要考虑这一点),因此您应该展开它以查看发生了什么。

垂直居中的关键是.content包裹网格布局的 flex 设置:

  • 通过使它成为一个弹性容器display: flex
  • 确保它与您想要居中的区域一样高,通过此处完成min-height: 100vh
  • 设置flex-direction: column使其项目垂直堆叠。(你可以不这样做,但这对我来说更有意义。)
  • 设置justify-content: center为内容居中。它垂直居中,因为那是弯曲方向轴。

你也可以通过一些地方项目和弹性或网格的组合到达那里。

html, body, p {
  margin: 0;
  padding: 0;
}

.header {
  position: fixed; /* don't move, no matter what */
  top: 0; /* position fixed removes it from the normal laytou flow, so we should tell it where to be */
  left: 0;
  right: 0;
  width: 100vw;
  background: lightskyblue;
  text-align: center;
}

.footer {
  /*
  same as .header above but pinned to bottom instead of top.
  you could reduce repetition by putting the common rules in their
  own class (.fixed or whatever) and then have a secondary class for
  .top or .bottom, but this is fine for the purposes of this demo.
  */
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100vw;
  background: lightskyblue;
  text-align: center;
}

.content {
  min-height: 100vh; /* as tall as the viewport because that's where we want to be centered */
  max-width: 80vw; /* limit width */
  margin: 0 auto; /* center horizontally */

  display: flex; /* vertical centering is easy with flex */
  flex-direction: column;
  justify-content: center; /* see? */
  
  /*
  you could also accomplish the vertical centering with
  flex-direction: row (the default) and align-items: center
  instead of justify-content, but this way makes more sense to
  me for whatever reason
  */
}

.content-grid {
  display: grid; /* establish the grid container */
  grid-template-columns: repeat(2, 50%); /* for this we only need 2 equal columns */
  grid-template-rows: 70px 50px 100px 100px; /* just ballpark/eyeballed row heights to make it vaguely resemble your example image */
  gap: 1rem; /* space between the blocks */
}

.content-grid > * {
  background: aliceblue; /* just so you can see it */
}

.content-grid > :nth-child(n + 3) { /* 1n + 3 translates as 'every one-th item starting at item 3' */
  /*
  make every block after the first two occupy the entire row.
  start at gridline 1, end at the last one (aka -1)
  */
  grid-column: 1 / -1; 
}
<div>
  <!-- HEADER -->
  <header class="header">
    <span>
      title
    </span>
  </header>

  <!-- BODY -->
  <div class="content">
    <div class="content-grid">
      <div>
        1
      </div>
      <div>
        2
      </div>
      <div>
       3
      </div>
      <div>
        4
      </div>
      <div>
        5
      </div>
    </div>
  </div>

  <!-- FOOTER -->
  <footer class="footer">
    <p>footer text</p>  
  </footer>
</div>


推荐阅读