别想太多:网格

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您的旅程每个阶段提供云产品。立即开始使用 价值 200 美元的免费积分!

绝大多数网站都使用网格。它们可能没有显式地使用网格系统,但如果它们有一个“主要内容区域”浮动到左侧,一个“侧边栏”浮动到右侧,那就是一个简单的网格。

如果出现更复杂的布局,人们往往会求助于网格框架。他们认为网格是这些超级困难的事情,最好留给超级 CSS 极客。这种想法是由他们所使用的许多网格系统本身非常复杂的事实所造成的。

请注意,这篇文章发布于 2012 年。浮动仍然是网格系统的首要方法,这篇文章侧重于真正简单的方法,就像仅仅浮动四个 25% 的元素,而不会对数学和奇特的间距系统感到疯狂。如今,我强烈建议使用 CSS 网格弹性盒 作为您的网格系统,如果您确实需要创建抽象网格的话。它可以说是更简单,而且肯定更灵活、更强大。

以下是我构建网格的方式。它并不难或复杂。即使使它们灵活也不是什么大问题。

上下文

块级元素的宽度与它所在的父元素一样宽 (width: auto;)。我们可以把它看作 100% 宽。网格的包装器可能与语义关系不大,它只是一个通用包装器,所以 div 就很好。

<div class="grid">
  <!-- 100% wide -->
</div>

让我们从一个实用且常见的需求开始:主要内容区域占 2/3 的宽度,侧边栏占 1/3 的宽度。我们只需要创建两个具有适当类名的列 div。

<div class="grid">
  <div class="col-2-3">
     Main Content
  </div>
  <div class="col-1-3">
     Sidebar
  </div>
</div>

要使它们并排显示,我们只需要将它们浮动并应用宽度。我们可以像这样选择它们

[class*='col-'] {
  float: left;
}

并像这样单独设置宽度

.col-2-3 {
  width: 66.66%;
}
.col-1-3 {
  width: 33.33%;
}

这就是别想太多网格的全部前提。

清除上下文

由于父元素只有浮动子元素,它将塌陷到零高度。让我们通过清除它来解决这个问题。如今,您只需要这样就可以了

.grid:after {
  content: "";
  display: table;
  clear: both;
}

间距

网格中最难的部分是间距。到目前为止,我们已经通过使用百分比来设置宽度,使我们的网格变得灵活。我们可以使数学计算变得复杂,并使用百分比来设置间距,但我个人不喜欢百分比间距,我喜欢固定像素大小的间距。此外,我们正试图避免对这些内容进行过多的思考。

第一步是使用 box-sizing: border-box;。我喜欢在所有内容上使用它。

*, *:after, *:before {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

现在,当我们设置宽度时,该元素保持该宽度,尽管应用了填充或边框。

第二步是在所有列(最后一个列除外)的右侧应用固定填充。

[class*='col-'] {
  padding-right: 20px;
}
[class*='col-']:last-of-type {
  padding-right: 0;
}

这就是基本间距的全部内容。

外部间距

需要外部间距吗?我喜欢为此使用一个选择性类

<div class="grid grid-pad">
  Grid with outside gutters also
</div>

第一步是向网格父元素添加左侧填充(并可选地添加顶部和底部填充)

.grid-pad {
  padding: 20px 0 20px 20px;
}

第二步是将右侧填充恢复到最后一列

.grid-pad > [class*='col-']:last-of-type {
  padding-right: 20px;
}

更多列选项

超级简单

.col-1-2 {
  width: 50%;
}
.col-1-4 {
  width: 25%;
}
.col-1-8 {
  width: 12.5%;
}

随心所欲。只要确保列分数加起来等于 1。是的,需要思考一下,但比平时更容易。

Sass

虽然我没有在这里大量使用它,但整个部分使用 SCSS/Compass 会变得更加简洁

* {
  @include box-sizing(border-box);
}

$pad: 20px;

.grid {
  background: white;
  margin: 0 0 $pad 0;
  
  &:after {
    /* Or @extend clearfix */
    content: "";
    display: table;
    clear: both;
  }
}

[class*='col-'] {
  float: left;
  padding-right: $pad;
  .grid &:last-of-type {
    padding-right: 0;
  }
}
.col-2-3 {
  width: 66.66%;
}
.col-1-3 {
  width: 33.33%;
}
.col-1-2 {
  width: 50%;
}
.col-1-4 {
  width: 25%;
}
.col-1-8 {
  width: 12.5%;
}

/* Opt-in outside padding */
.grid-pad {
  padding: $pad 0 $pad $pad;
  [class*='col-']:last-of-type {
    padding-right: $pad;
  }
}

模块

我喜欢在这些网格中使用“模块”。

<div class="grid">
  <div class="col-2-3">
     <article class="module">
        stuff
     </article>
     <article class="module">
        stuff
     </article>
  </div>
  <div class="col-1-3">
    <aside class="module">
       Sidebar stuff. Sub modules?
    </aside>
  </div>
</div>

以这种方式将内容分解成片段感觉很好。额外的副作用是,每个模块都可以有自己的填充,从而使文本远离网格的边缘。

结果

这里有一个 CodePen 上的演示

浏览器等等

在 IE 8 及更高版本以及所有其他标准内容中都非常有效。如果您需要 IE 7 支持,您将不得不做其他事情 =)。

此外,弹性盒 将使此过程变得更加容易和更好(以多种方式,包括按需重新排序),但我认为我们还需要大约一年时间才能开始考虑使用它。

相关

查看 OOCSS 网格