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

CSS栅格系统已经面世很久了,经常在一些CSS框架中可以看见它的身影,比如Boostrap。我不并讨厌Boostrap,但是有时候如果你只是需要一个栅格功能而去引入整个框架,就显得小题大做了。接下来,我将从零开始,教你一步步打造属于自己的CSS栅格系统。

CSS栅格系统的组成元素

正如我们所见,基本的栅格包含一下元素:

  • 一个容器
  • 列与列之间的间隔

    容器

容器的作用是为整个栅格设置宽度。一般将栅格的宽度设置为100%,但是在大屏幕下,也可为其设置一个max-width属性。

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

行的作用是保证自身里面的列不会溢出到其他的行。为了实现这一点,我们使用清除技巧来使行内的元素都会显示在行里面。

1
2
3
4
5
6
.row:before,
.row:after {
content: '';
display: table;
clear: both;
}

列无疑是栅格系统里最复杂的部分了。首先,列在CSS里面有几种不同的定位方式,还要考虑到列的不同宽度,同时响应式设计也是要考虑到的因素。在这个教程里,我们主要解决列的定位和宽度问题。响应式我会留一部分到下次再讲。

列的定位

float布局,inline-blocks布局,display-table布局,display-flex布局,这些是用来定位列的不同方法。根据我的个人经验,这些方法里面最不容易出错和运用最广泛的是float布局。然而,当列的内容为空的时候,浮动的列将互相堆叠。为了避免这种情况,我们为列设置一个1px的min-height属性,同时设置float属性。

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

列的宽度

为了找出列的宽度,我们要做的是将容器的总宽度按列的总数来切分。在我们的教程中,行的宽度是100%,我们将一行设置为包含6个列,这样列的宽度就是100%/6=16.66%。

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

当然这只是第一步,如果我们想要一个2倍列宽的块,我们就需要一个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(或者任何其他的列总数,根据你之前的切分数而定)。

列与列之间的间隔

在设置box-sizing属性值为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;
}

(就我自己而言,我会在我的CSS样式里使用* {box-sizing: border-box;} ,这样页面里所有的元素都是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>
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
.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;
}

为你的栅格加上响应式

调整栅格系统以适应移动端布局并不困难,我们要做的只是调整列的宽度。

为了简单起见,在屏幕宽度小于800px时,我将列的宽度进行放大为两倍。

唯一需要注意的例外情况是,有些时候行的最后一列会超出列。比如当.clo-2的列和.col-1的列跟在.col-5的列旁边时,就会出现这种情况。

为了应对这种情况,我们将处于列尾部的.col-1和.col-2的列的宽设置为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宽度的屏幕,我们将除了最小列之外的其他列的宽度设置为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栅格系统的创建过程。

译者补充

这份教程简单易懂地介绍了如何一步一步建立CSS栅格系统。参照Boostrap,栅格系统的响应式功能可以进一步扩展。

增加lg和md样式,利用媒体查询,在不同的浏览器尺寸下应用不同的CSS类。

屏幕宽大于768px时,增加样式

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
@media all and (min-width: 768px) {
.col-lg-1 {
width: 8.33%;
}
.col-lg-2 {
width: 16.66%;
}
.col-lg-3 {
width: 25%;
}
.col-lg-4 {
width: 33.33%;
}
.col-lg-5 {
width: 41.66%;
}
.col-lg-6 {
width: 50%;
}
.col-lg-7 {
width: 58.33%;
}
.col-lg-8 {
width: 66.66%;
}
.col-lg-9 {
width: 75%;
}
.col-lg-10 {
width: 83.33%;
}
.col-lg-11 {
width: 91.66%;
}
.col-lg-12 {
width: 100%;
}
}

屏幕宽小于768px时

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
@media all and (max-width: 768px) {
.col-md-1 {
width: 8.33%;
}
.col-md-2 {
width: 16.66%;
}
.col-md-3 {
width: 25%;
}
.col-md-4 {
width: 33.33%;
}
.col-md-5 {
width: 41.66%;
}
.col-md-6 {
width: 50%;
}
.col-md-7 {
width: 58.33%;
}
.col-md-8 {
width: 66.66%;
}
.col-md-9 {
width: 75%;
}
.col-md-10 {
width: 83.33%;
}
.col-md-11 {
width: 91.66%;
}
.col-md-12 {
width: 100%;
}
}

html里面这样使用

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
<body>
<div class="wrap">
<div class="row">
<div class="col-lg-4 col-md-6">
<div class="content"></div>
</div>
<div class="col-lg-4 col-md-6">
<div class="content"></div>
</div>
<div class="col-lg-4 col-md-12">
<div class="content"></div>
</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-3">
<div class="content"></div>
</div>
<div class="col-lg-6 col-md-6">
<div class="content"></div>
</div>
<div class="col-lg-3 col-md-3">
<div class="content"></div>
</div>
</div>
<div class="row">
<div class="col-lg-1 col-md-2">
<div class="content"></div>
</div>
<div class="col-lg-1 col-md-2">
<div class="content"></div>
</div>
<div class="col-lg-2 col-md-8">
<div class="content"></div>
</div>
<div class="col-lg-2 col-md-3">
<div class="content"></div>
</div>
<div class="col-lg-6 col-md-3">
<div class="content"></div>
</div>
</div>
</div>
</body>

使用css预编译器编写上面的css更加方便

1
2
3
4
5
6
7
8
9
10
11
12
getGridWidth(n)
n/12*100%

@media all and (min-width:768px)
for n in 1..12
.col-lg-{n}
width getGridWidth(n)

@media all and (max-width:768px)
for n in 1..12
.col-md-{n}
width getGridWidth(n)

最终效果展示

http://60kmlh.ink/css-grid/