1. 介绍

本文主要讲解 Bootstrap3 的栅格布局实现原理,以及实际使用中应该注意的问题。

栅格系统这些本来是隐藏在后面的东西,直接使用就可以,没必要去了解其真正的工作原理。除非你的布局出问题了,比如写一些复杂的页面,spacing,margin,padding 等这些全都乱了,特别在写某些需要动态调整的页面时。

很多人都对 Bootstrap 的栅格系统不太理解,得解释很多遍。所以我更倾向于用可视化的方式,来解释 Bootstrap 栅格系统是怎么工作的,这样更容易理解。让我们一起看看 Bootstrap 是如何巧妙的实现栅格系统的。

2. 原理

Bootstrap 的基本使用是这样的:

<div class="container">
    <div class="row">
        <div class="col-xs-12"></div>
    </div>
</div>

2.1 Container 容器

container 类有两个目的:

  1. 为响应式提供宽度约束。响应式尺寸的改变其实改变的是 container,行(rows)和列(columns)都是基于百分比的,不用改变;
  2. 提供内补(padding)使内容不至于紧贴在浏览器边缘,左右两边都是 15px 的 padding 值,下图中用粉色标出,稍后详细解释。

切记,不要在一个 container 中嵌套另一个 container。

file

2.2 Row 行

行(row)为容纳列(column)提供了空间,默认一行分为 12 列,因为所有列都是左浮动的,行自然也就扮演了容器的角色。

行(row)的两侧拥有独特的 -15px 的 margin 值,如下图蓝色部分所示。行(row)被约束在容器(container)内,边缘与粉色区域的边缘重叠,但是没有超出。这里 -15px 的 margin 值把行(row)向两边延伸,最终抵消了容器(container)15px 的 padding。为什么这么做呢?后面介绍列时我们会知道。

不要在 container 外使用 row,不起作用。

file

2.3 Column 列

列拥有 15px 的 padding 值,在下图中用黄色部分表示。列的 padding 值使得列的边缘与行的边缘重叠了。同时由于行有负的 margin 值,容器有正的 padding 值,行和容器(container)的边缘也正好重叠。列的 padding 值为列与列的内容之间提供了 30px 的间隔。

不要在 row 外使用 col,不起作用。

file

2.4 Content Within a Column 列内内容

列的 padding 给内容提供了空白,让内容不至于紧贴在浏览器边界上,列和列的内容之间也有了 padding。这就是 container、row、column 最终要达到的设计效果。

file

2.5 Nesting 嵌套

使用了 container,row,column 后,可以在列内再增加新的栅格。例如,在右侧的列内添加新的行时就不需要再在 container 中了。

file

这个技巧在于列扮演了 container 一样的角色,列也有 15px 的 padding,一样可以和 row 的负 margin 值相抵消,同时在内容的两侧留白。

file

2.6 Offsets 偏移

偏移的实现相当简单,仅仅是在列(col)的左侧加上了 margin 值。

唯一比较怪的地方可能是最左侧的 col 是从 -15px 的 row 的 margin 值开始偏移的,中间的列的偏移则是直接从前一个列开始偏移,分割列并在列内容的两侧留出补白。除此之外,偏移和列(col)是一样的。

file

2.7 Push and Pull 列的排序

首先我们为什么需要对列进行排序:为了响应式的调整布局。比如说,在移动设备上使用移动端布局,在桌面上使用桌面布局,push 和 pull 允许你打破 HTML 中从上到下自左向右的布局方式。

让人更困惑的是 push pull 的实现是通过添加 position 而不是通过添加 margin 值来实现。push 添加的是 left 值,pull 添加的是 right 值。因为它们是浮动的,并且被包含在一个相对定位的容器中,行会根据你设置的距离进行对应的移动,比如,col-sm-push-4。

file

这就出问题了,它会导致列重叠,而不像正常的列或者列的偏移。

所以大体是这样,当你 push 或 pull 之后,相应的还需要一个「互补」的操作。如果你 push 一个列到右侧,那么还要以对应的距离 pull 右侧的列到左侧。

file

3. 背后的原理

3.1 Container

container 使得内容两侧能够有 15px 的空白,而不需要为 body 元素设置 15px 的 padding。否则可能会让非 Bootstrap 的 div 元素不能到达浏览器边缘,这对使用全屏背景色的 div 元素来说,很成问题。

3.2 Row

row 拥有负的 margin 值,并且值等于 container 的 padding 值,所以边界与 container 得以重叠,负的 margin 值抵消了 padding,这让 row 没有被 container 的 padding 所影响。

3.3 Columns

col 也拥有 15px 的 padding 值,使得内容和容器边缘有 15px 的空白,并且在相邻列的内容之间也有 15px + 15px 的留白。这就不需要单独为第一列或最后一列设置 padding。现在,不管怎样,在列内容和列边缘之间总是留有 15px 的空白。

3.4 Nested Rows

嵌套行的原理和上面一样,行的负 margin 值抵消了列的 padding,本质上列扮演了 container 的角色,所以嵌套行时不再需要 container。

3.5 Nested Columns

嵌套列和上面一样的。

3.6 Offsets

偏移的本质就是通过增加空白间隔达到你想要的距离,非常的简单。

3.7 Push/Pull

push 和 pull 用于在移动端到桌面端布局切换来调整左右列的位置,或者,当有一个特别的布局而 offset 偏移无效时。

4. 常见问题

下面会列举一些经常遇到的问题,绝大多数在 HTML 代码中很容易就能看出来。

4.1 缺少 container

第一个就是少了 container。没有 container 意味着没有 padding 与行(row)的负 margin 值相抵消,意味着行会超出父元素。当元素处于浏览器边缘时,造成奇怪的横向滚动。

file

4.2 缺少 row

第二个类似的问题就是少了 row,这与缺少 container 产生的问题相反,content 与浏览器(可视区)的边缘有了 30px 的距离,比正常值多了一倍。而且你的浮动也会产生问题。由于缺少了外面 row 的包裹,浮动没有得到正常的清除,导致浮动可能产生问题。

同样,当试图嵌套栅格系统时,新嵌进去的 content 离左侧的边距达到了 45px。

file

4.3 其它元素里面嵌套 container

在其它任意元素内嵌套 container 和列相比增加了新的 padding,同时也增加了 container 独有的响应式特性。

file

4.4 偏移/push/pull

当使用偏移或者 push/pull 时,偏移很简单不会出现什么问题,只是让列更宽了。push/pull 不同,如果你 push 太多,列会超出它的 container,注意使用合适的值就不会有问题。

file

上面就是使用 Bootstrap3 的栅格系统时经常会碰到的一些问题,如果你在页面有很多的嵌套布局碰到问题,或者你的响应式布局没按照你所预想的方式工作,先看看上面这几点。

5. 最后

这就是 Bootstrap3 的栅格系统工作原理。它真的很聪明并且提供了极好的解决方案。在这么多年使用栅格系统的经验中,我个人觉得它是实现的最优雅的。

英文原文链接