[译]构建自己的CSS栅格系统

原文地址: http://j4n.co/blog/Creating-your-own-css-grid-system

CSS栅格已经出现很长时间了,它们经常会被包含在一些框架中,就像Bootstrap。我并不厌恶Bootstarp,但当你需要栅格布局而且使用框架是得不偿失的。那么怎样才能构建我们自己的CSS栅格布局呢?

CSS栅格布局的基本构成

http://j4n.co/content/4-blog/10-Creating-your-own-css-grid-system/grid-elements.png

一个基本的栅格,包含以下几个部分:

  • a container(容器)
  • rows(行)
  • columns(列)
  • gutters(列与列中的间隙)

The Container(容器)

http://j4n.co/content/4-blog/10-Creating-your-own-css-grid-system/container.png

容器的目的在于控制内部栅格的总宽度。一般来说,容器的宽度为100%,但为了大屏显示,你可能需要设置一个最大宽度。

1
2
3
4
.grid-container {
width : 100%;
max-width : 1200px;
}

The Row(行)

http://j4n.co/content/4-blog/10-Creating-your-own-css-grid-system/row.png

行的目的在于保证列不向别的行溢出,我们使用浮动清除去保证任何在行内的元素仍在行内。

1
2
3
4
5
6
7
/*-- 浮动清除 -- */
.row:before,
.row:after {
content: "";
display: table ;
clear: both;
}

The Column(列)

http://j4n.co/content/4-blog/10-Creating-your-own-css-grid-system/column.png

列是栅格系统中比较复杂的一部分。首先,在CSS中有各种各样的方法去定位列,由于响应式设计等因素,也有多种宽度需要去考虑。在本文中,我们将会定位列并给予它们宽度,我将暂时不考虑响应式。

Column Positioning(列定位)

Floats, inline-blocks, display-table, display-flex. 各种不同的方法在CSS中定位列。就我的经验来看,最少错误的可能与最广泛的使用就是float方法了。如果我们的列是空的,浮动的列将会相互堆叠 。为了避免,我们为列设置了最小宽度。

1
2
3
4
[class*='col-'] {
float: left;
min-height: 1px;
}

Column Widths(列宽度)

为了求得一个列的宽度,我们必须根据容器的宽度去划分列。在我的例子中,容器的宽度是100%,我们需要6列,100/6=16.6,所以我们列的宽度是16.66%。

1
2
3
4
5
[class*='col-'] {
float: left;
min-height: 1px;
width: 16.66%;
}

当然,这仅仅是个开始。如果我们需要一个部分有2列宽,我们需要创建一列具有两列宽,计算是十分简单的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.col-1{
width: 16.66%;
}
.col-2{
width: 33.33%;
}
.col-3{
width: 50%;
}
.col-4{
width: 66.664%;
}
.col-5{
width: 83.33%;
}
.col-6{
width: 100%;
}

唯一一件我们需要考虑的事情是当我们将不同的列混合组合时,它的宽度号加起来要等于6。

Column Gutters(列间空隙)

http://j4n.co/content/4-blog/10-Creating-your-own-css-grid-system/column-gutters.png

border-box盒模型之前,一个百分比控制宽度的元素去设置静态的padding是十分痛苦的。幸运的是,使用border-box我们能够容易得创建空隙。

1
2
3
4
5
6
7
8
9
10
11
12
/*-- 设置栅格布局中所有元素都是border-box --*/
.grid-container *{
box-sizing: border-box;
}
[class*='col-'] {
float: left;
min-height: 1px;
width: 16.66%;
/*-- 空隙 --*/
padding: 12px;
}

(个人角度讲,我使用* {box-sizing: border-box;}在我的CSS里,去允许页面中任何元素都是border-box)。

栅格布局基本完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="grid-container outline">
<div class="row">
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
</div>
<div class="row">
<div class="col-2"><p>col-2</p></div>
<div class="col-2"><p>col-2</p></div>
<div class="col-2"><p>col-2</p></div>
</div>
<div class="row">
<div class="col-3"><p>col-3</p></div>
<div class="col-3"><p>col-3</p></div>
</div>
</div>

完整的HTML与CSS如下:

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
* {
box-sizing: border-box;
}
.grid-container{
width: 100%;
max-width: 1200px;
}
/*-- 浮动清除 -- */
.row:before,
.row:after {
content: "";
display: table;
clear: both;
}
[class*='col-'] {
float: left;
min-height: 1px;
width: 16.66%;
/*-- 空隙 -- */
padding: 12px;
background-color: #FFDCDC;
}
.col-1{ width: 16.66%; }
.col-2{ width: 33.33%; }
.col-3{ width: 50%; }
.col-4{ width: 66.66%; }
.col-5{ width: 83.33%; }
.col-6{ width: 100%; }
.outline, .outline *{
outline: 1px solid #F6A1A1;
}
/*-- 列内元素的样式 --*/
[class*='col-'] > p {
background-color: #FFC2C2;
padding: 0;
margin: 0;
text-align: center;
color: white;
}

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="grid-container outline">
<div class="row">
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
</div>
<div class="row">
<div class="col-2"><p>col-2</p></div>
<div class="col-2"><p>col-2</p></div>
<div class="col-2"><p>col-2</p></div>
</div>
<div class="row">
<div class="col-3"><p>col-3</p></div>
<div class="col-3"><p>col-3</p></div>
</div>
</div>

响应式的栅格系统

使我们的栅格系统适应手机屏幕是十分简单的,我们必须去适应列的宽度。

为了这简单的目的,在800px的屏幕下我将加倍列的宽度。

只有一件事情看上去是例外的,行中的最后一列可能会单独成行,像3个col-2,col-5与col-1。我们将最后的.col-2.col-1行宽设为100%。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@media all and (max-width:800px){
.col-1{ width: 33.33%; }
.col-2{ width: 50%; }
.col-3{ width: 83.33%; }
.col-4{ width: 100%; }
.col-5{ width: 100%; }
.col-6{ width: 100%; }
.row .col-2:last-of-type{
width: 100%;
}
.row .col-5 ~ .col-1{
width: 100%;
}
}

当屏幕比800px更小时,我们除了col-1以外,其余列width均设为100%。

1
2
3
4
5
6
7
8
@media all and (max-width:650px){
.col-1{ width: 50%; }
.col-2{ width: 100%; }
.col-3{ width: 100%; }
.col-4{ width: 100%; }
.col-5{ width: 100%; }
.col-6{ width: 100%; }
}

现在我们可以在不使用框架的情况下,建立自己的响应式栅格系统了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<div class="grid-container outline">
<div class="row">
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
<div class="col-1"><p>col-1</p></div>
</div>
<div class="row">
<div class="col-2"><p>col-2</p></div>
<div class="col-2"><p>col-2</p></div>
<div class="col-2"><p>col-2</p></div>
</div>
<div class="row">
<div class="col-3"><p>col-3</p></div>
<div class="col-3"><p>col-3</p></div>
</div>
<div class="row">
<div class="col-4"><p>col-4</p></div>
<div class="col-2"><p>col-2</p></div>
</div>
<div class="row">
<div class="col-5"><p>col-5</p></div>
<div class="col-1"><p>col-1</p></div>
</div>
<div class="row">
<div class="col-6"><p>col-6</p></div>
</div>
</div>

不过本文仅仅是构建栅格系统的初步要点。虽然这不是框架或是复杂的解决方案,但我希望它为建立CSS栅格系统提供了一个简明的过程。