给定容器中的项目网格,如何处理导致项目溢出的边距?

Given a grid of items in a container, how to handle margins from causing items to overflow?

我有一个 608px 宽的容器,我的设计要求每行有 3 个项目。其中每个项目是 192px。并且只有行中的前 2 项的 margin-right16px

问题是 CSS 正在向所有项目添加 margin-right16px

我如何更新代码以使其每行 3 个项目,而每行只有第一个和第二个项目有 margin-right 填充?

我有一个 hacky 版本,我在其中制作了 margin-rightmargin-left 8px,然后在容器上添加了负 -8px 边距,但这感觉很 hacky 和我很好奇现在是否有一种更优雅的方式来实现 CSS3.

.container {
  width: 608px;
  min-width: 608px;
  max-width: 608px;
  background: #efefef;
  display: flex;
  flex-wrap: wrap;
}

.item {
  width: 192px;
  min-width: 192px;
  max-width: 192px;
  margin: 0 16px 16px 0;
  border: 1px solid #ccc;
  box-sizing: border-box;
}
<div class="container">
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>

在 flexbox 中,您可以使用 justify-content 属性 来选择当项目未连续用完所有剩余 space 时您希望如何对齐项目。在这种情况下,只需删除边距并在容器上使用 justify-content: space-between 即可完成您想要的操作。在这种情况下,justify-content: space-between 将自动平衡项目之间行中剩余的 space。

.container {
  width: 608px;
  min-width: 608px;
  max-width: 608px;
  background: #efefef;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  width: 192px;
  min-width: 192px;
  max-width: 192px;
  border: 1px solid #ccc;
  box-sizing: border-box;
}
<div class="container">
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>

如果您不使用 flexbox,另一种选择是仅选择三分之一 .item class 并使用 nth-of-type() 选择器从中删除 margin-right :

.item:nth-of-type(3n) {
  margin-right: 0;
}

您可以添加伪选择器 nth-child(3n+3) 以删除每个 .item 的右边距,它是 3 的倍数(即 3,6,9...)。尝试将这段代码添加到您的代码中。

.item:nth-child(3n+3) {
  margin-right: 0;
}

这里是 CSS-grid 解决方案,您可以轻松控制元素之间的间隙,也不需要为它们明确指定宽度:

.container {
  width: 608px;
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  grid-column-gap:16px;
  background: #efefef;
}

.item {
  border: 1px solid #ccc;
  box-sizing: border-box;
}
<div class="container">
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>

这些是您的布局要求:

  • 每行三个项目
  • 每个项目的宽度为 192px
  • 容器宽度为 608px
  • 项目之间的 space 必须为 16px
  • 项目和容器之间的 space 必须为 0px。

嗯,你已经计算过了,所以你甚至不需要使用边距。

192 * 3 = 576

576 + 16 + 16 = 608

由于您已计算容器的宽度以容纳三个项目,再加上一个 额外的 32 像素免费 space,边距是不必要的。使用 justify-content,旨在免费分发 space。

8.2. Axis Alignment: the justify-content property

The justify-content property aligns flex items along the main axis of the current line of the flex container. [...] It helps distribute free space when all the flex items on a line are inflexible.

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between; /* NEW */
  width: 608px;
  background: #efefef;
}

.item {
  flex: 0 0 192px;
  border: 1px solid #ccc;
  box-sizing: border-box;
}
<div class="container">
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>

但是你的问题结尾是:

I'm curious if there is now a more elegant way to accomplish this with CSS3.

如果项目、间距 and/or 容器长度不同,那么是。

本质上,您的目标是创建 "gutters",这意味着项目之间 space,而不是项目与容器之间。

Flexbox 提供标准边距(如您所见,这可能会在多行容器中造成问题)和对齐属性(如 justify-contentalign-items,除非您事先做数学)。

因此,当间距很重要时,flexbox 不是最佳解决方案。它没有提供在项目之间创建 space 的自然方法,也没有在项目和容器之间应用 space。

但是,在 CSS Grid Layout 中,装订线不是问题,它提供了水平和垂直间隙的特定属性:

  • row-gap
  • column-gap
  • gap(两者的 shorthand)

这些属性在网格项之间创建 space,但在项和容器之间不创建。

10.1. Gutters: the row-gap, column-gap, and gap properties

The row-gap and column-gap properties (and their gap shorthand), when specified on a grid container, define the gutters between grid rows and grid columns.

注意 最近修订了 CSS 网格规范。这些属性以前被列为 grid-column-gapgrid-row-gapgrid-gap (reference)。出于兼容性目的,我在下面的示例中使用了这些版本。

.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, 192px);
  grid-column-gap: 16px;
  width: 608px;
  background: #efefef;
}

.item {
  border: 1px solid #ccc;
  box-sizing: border-box;
}
<div class="container">
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
  <div class="item">Item</div>
</div>