回归基础:我们应该使用 Flexbox 还是 Grid?

2025-05-28

回归基础:我们应该使用 Flexbox 还是 Grid?

《回归基础》将解答我刚开始学习 CSS 时的一些疑问。我个人认为,开始学习 CSS 会非常困难,因为 CSS 大约有 520 个属性可以使用。当然,我们不会全部用到,还有很多属性我还不了解,但要精通 CSS,我们需要理解很多属性。这篇博客不会从最基础的 CSS 开始讲解,但我会尝试向你展示实现方法。

如果您以前从未使用过 flexbox 或 grid,您可以查看css-tricks 的flexbox 指南grid 指南。


问题

我们什么时候应该使用 flex 或 grid?

刚开始学习 CSS 并了解 flexbox 和 grid 的时候,我有点困惑该何时使用 flexbox 和 grid。在这篇博客中,我将尝试解释如何根据具体情况在 flexbox 和 grid 之间进行选择。


使用 Flex 的用例

我总是使用 flex 来创建只有一个维度(水平或垂直)的布局。在这篇博客中,我将结合我做过的一些项目,提供一些 flexbox 的使用案例。

1. 所有元素水平和垂直方向均位于中心的容器

我们通常在登陆页面看到这个

例子:

为了实现这个布局,我们只需要3行CSS,我建议你记住这个组合,因为你将在很多情况下使用它。

.container {
  /*  make sure the parent element has height */
  min-height: 100vh;
  /* css to align vertically and horizontally */
  display: flex;
  align-items: center;
  justify-content: center;
}

/* If you want to make a full-page,
make sure the container has a height of the viewport */
Enter fullscreen mode Exit fullscreen mode

2. 将页面分成几个部分

这种布局也很常见,通常将容器分成2个宽度相同的部分,我们也可以将其分成3个,4个或任意多个。

Codepen

这个布局可以通过使用 flex 轻松实现,我们先看看 HTML

<div class="container">
  <div class="content">
    <h1>Hello Bambang</h1>
    <p>welcome to my page</p>
    <button>click me</button>
  </div>
  <img class="content" src="https://unsplash.it/700/600" alt="unsplash" />
</div>
Enter fullscreen mode Exit fullscreen mode

我们可以看到,它div.container有 2 个项目,分别是div.contentimg.content,所以我们可以制作相等部分的布局。

.container {
  min-height: 100vh;
  display: flex;
}

.content {
  /* this will make it divides in equal parts */
  width: 100%;

  /* you should use flex-basis for this, but flex-basis didn't really works on images, so I use width */
  /* flex-basis: 100%; */
  /* other tag like div works well tho! */
}

div.content {
  /* the first flexbox use case */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

img.content {
  object-fit: cover;
}
Enter fullscreen mode Exit fullscreen mode

通过使用,width: 100%我们让子元素占用尽可能多的空间。因为它们都希望达到 100%,所以它们妥协并跨越了 50% 的空间。

请注意,为了兼容 IE,你应该width: 100%用替换flex-basis: 100%(感谢 Ihor Vorotnov),但我特意在这里使用了 width,因为 flex-basis 不适用于图像。在其他标签上,比如 div 或标题,它就可以正常工作。

我们还可以将宽度或 flex-basis 硬编码为 50%,但是这样做违背了将内容划分为相等部分的目的,因为我们需要在每次添加新子项时更改百分比。

如果我们想用这个布局制作一个响应式设计,我们可以利用flex-direction

.container {
  min-height: 100vh;
  display: flex;
  /* add this to make the flex stacked vertically */
  flex-direction: column;
}

@media (min-width: 700px) {
  .container {
    flex-direction: row;
  }
}
Enter fullscreen mode Exit fullscreen mode

因此,当我们处于移动视图中时,flex 将垂直堆叠(就像 HTML 的正常工作方式一样),而当我们进入更大的视口时,flex 将使子元素水平堆叠(检查 codepen 中的演示)

3.创建导航栏(使用空格)

Codepen

创建一个简单的导航栏是很常见的事,通常布局是分开的,左侧是徽标,右侧是导航。


<nav>
  <h3>Home</h3>
  <ul>
    <li>Route</li>
    <li>Route</li>
  </ul>
</nav>
Enter fullscreen mode Exit fullscreen mode

nav有两个子元素,分别是h3ul。接下来,我们只需要重置基础样式,并使用 space-between 分隔子元素

nav {
  background-color: lightblue;
  display: flex;
  align-items: center;

  /* this property will make the child spaced apart */
  justify-content: space-between;
}

ul {
  /* remove bullet style */
  list-style: none;
  display: flex;
}

ul > li + li {
  /* add space between navigation links */
  margin-left: 2em;
}
Enter fullscreen mode Exit fullscreen mode

以上所有示例实际上都可以用网格来实现。但是,使用网格比使用弹性盒子需要编写更多的 CSS。


使用网格的用例

Codepen

网格通常用于实现更复杂的布局。我的决定是:如果 flex 太难,那就用 grid

使用flex布局其实也可以实现复杂的布局,但是使用grid会简单很多。

1.制作二维布局

我通常使用网格来创建这种布局,因为它有一个gap功能可以将它们隔开。如果我们想要实现响应式设计,使用弹性元素来隔开元素会更加困难。

如果使用网格,这样的布局会非常简单,我们只需要将其分成两列即可。

<div class="container">
  <div class="item">item1</div>
  <div class="item">item2</div>
  <div class="item">item3</div>
</div>
Enter fullscreen mode Exit fullscreen mode

div.container我们将使用和 3来简化布局div.item

.container {
  /* container base layout */
  max-width: 700px;
  margin: 0 auto;

  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1em;
}

.item {
  border: 0.2px solid white;
  height: 15em;
}
Enter fullscreen mode Exit fullscreen mode

通过使用,grid-template-columns: repeat(2, 1fr)我们设置网格将列分为两列,并且item将遵循我们设置的规则。最后,我们添加gap: 1em来创建一些空白。

网格在响应式设计中非常有用,我们只需要将 grid-tem 上的规则更改为在较小屏幕尺寸下为 1 列,在较大屏幕尺寸下为 2 列

.container {
  /* container base layout */
  max-width: 700px;
  margin: 0 auto;

  display: grid;
  /* no need to add grid template, because grid defaults to 1 column */
  gap: 1em;
}

@media (min-width: 700px) {
  .container {
    grid-template-columns: repeat(2, 1fr);
  }
}
Enter fullscreen mode Exit fullscreen mode

2. 制作不同尺寸的布局

Codepen

我建议您使用 Firefox Dev Tools 来查看指示网格编号的线条。

我们通过设置 4 列 2 行来实现这种布局,然后为每个元素指定行和列的位置。例如,第一张图片跨越 2 列 2 行。如果您还不了解网格编号系统,请查看此处。

<div class="container">
  <div class="item item1">item1</div>
  <div class="item item2">item2</div>
  <div class="item item3">item3</div>
  <div class="item item4">item4</div>
</div>
Enter fullscreen mode Exit fullscreen mode

.container我们将使用作为父级来简化布局。

.container {
  max-width: 700px;
  margin: 0 auto;

  display: grid;
  /* makes the grid into 4 columns and 2 rows */
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 1fr);
}

.item {
  border: 1px solid white;
  min-height: 10rem;
}

.item1 {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}

.item2 {
  grid-column: 3 / 5;
}

/* you can also give value to item 3 and 4,
but because it follows the natural flow of the grid I won't continue */
Enter fullscreen mode Exit fullscreen mode

对于响应式设计,我们可以根据我们想要的行和列放置图像,我们也可以更改模板


概括

如果使用 flex 变得太复杂,请使用 Grid


最初发布在我的个人网站上,在我的网站上可以找到更多博客文章代码片段库,以便于访问🚀

文章来源:https://dev.to/theodorusclarence/back-to-basic-should-we-use-flexbox-or-grid-1h9i
PREV
无需编译即可使用 Typescript
NEXT
2022 年掌握编程的 7 大平台