深度了解bootstrap源码之sass篇(十五)

前言

这篇文章主要研究_gird.scss。

研究对象

gird.scss、_gird.scss(mixins)、_gird-framework.scss。这三个文件组成bs网格布局系统,我是这么理解它们之间的关系的。类似用积木搭建筑。

_gird-framework.scss 创建所需积木的方法集合。

_gird.scss(mixins) 创建搭建”环境”的方法。

gird.scss 实例化”环境”,在环境内发出带明确旨意的指令(@include)

grid.scss

源文:

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//
// 布局系统
// --------------------------------------------------
// 以下是容器宽度
//
// 设置容器的宽度,和重写"导航条(navbars)"的自适应(media queries)
.container {
// 该方法auto了左右外边距,设置了各15px的内边距,调用了clearfix清除了浮动。
@include container-fixed;
@media (min-width: $screen-sm-min) {
// 该方法指向720px + grid-gutter-width(模块间距,默认30px,在bs框架中,模块之间间距是15px,所以总合是30px)
width: $container-sm;
}
@media (min-width: $screen-md-min) {
// 该方法指向940px + grid-gutter-width
width: $container-md;
}
@media (min-width: $screen-lg-min) {
// 该方法指向1140px + grid-gutter-width
width: $container-lg;
}
}
// 以下是流式栅格布局
//
// 利用mixin方法意味着固定了容器的宽度,但并没有定义流体宽度,以下是流式布局实现
.container-fluid {
// 该方法auto了左右外边距,设置了各15px的内边距,调用了clearfix清除了浮动。
@include container-fixed;
}
// 以下是 一列网格(至多12个)容器
//
// 包含了清除浮动的样式
.row {
// 该方法内部设置入参$gutter默认值为30,并添加负的左右外边距为15px用于抵消.container 元素设置的 padding,也就间接为“行(row)”所包含的“列(column)”抵消掉了padding,该方法还调用clearfix清除了浮动。
@include make-row;
}
// 以下是网格样式
//
// 包含了(xs,sm,md,lg)四种尺寸的通用样式
// make-grid-columns方法实现了网格布局的框架。
// 该方法调用自grid-framework,接受两个参数,方法给两个参数定义了默认值。第一个参数代表起始索引(i:1),第二个参数是四种尺寸的网格样式名(eg:col-xs-#{$i},...)。
// 利用for循环将四种尺寸的网格样式名从1至12的顺序遍历出来,将结果值迭代到第二个参数。
// 最终得出来的值为网格框架,将其作为样式名赋予通用样式:相对定位、15px的左右内边距、最低1px的高度。
@include make-grid-columns;
// 细说一下make-grid(size)方法功能点: 该方法可以说被抽象为组件,调用了多个方法,是多个方法的集合。调用自grid-framework。
// ①:给每个xs尺寸的网格(col-size-1 ~ col-size-12)添加float:left属性,实现技巧同上↑ 也是利用for循环遍历;
// ②:给每个xs尺寸的网格(col-size-1 ~ col-size-12)定义了对应的宽(百分比);
// ③:实现了列偏移(列向右偏移);
// ④:实现了顺序转换(列顺序转换),该功能事实上也是向左、右偏移的方式实现列顺序转换。顺序转换和偏移的区别在于,偏移过程中是列外向右边距值的变化,顺序转换是左右left和right值的变化。两者向右偏移的效果相同,但是过程是不同的;
// ⑤:处理了size为0的情况:对应各类方法的属性值赋为auto。
// 以下是xs尺寸的网格
//
// 作用于适配宽度低于768px的设配。
@include make-grid(xs);
// sm尺寸的网格
//
// 适配宽度高于768px的设配,仅在当前可视区宽度大于768px时有效。同时覆盖网格为xs尺寸的样式。
@media (min-width: $screen-sm-min) {
@include make-grid(sm);
}
// md尺寸的网格
//
// 适配宽度高于992px的设配,仅在当前可视区宽度大于992px时有效。同时覆盖网格为sm尺寸的样式。
@media (min-width: $screen-md-min) {
@include make-grid(md);
}
// lg尺寸的网格
//
// 适配宽度高于1200px的设配,仅在当前可视区宽度大于1200px时有效。同时覆盖网格为md尺寸的样式。
@media (min-width: $screen-lg-min) {
@include make-grid(lg);
}

_grid.scss(mixins)

源文:

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// 网格系统
//
// 使盒子(container)垂直居中
@mixin container-fixed($gutter: $grid-gutter-width) { // 30px,表示块与块之间的距离。
margin-right: auto;
margin-left: auto;
padding-left: ($gutter / 2);
padding-right: ($gutter / 2);
@include clearfix;
}
// row,用于一列网格布局的容器,bootstrap一列最多为12格
@mixin make-row($gutter: $grid-gutter-width) {
margin-left: ($gutter / -2);
margin-right: ($gutter / -2);
@include clearfix;
}
// ------------------------------------------------
// 以下方法没看到有被调用,从代码上来看,在grid-frameword中make-grid方法已经实现了以下功能,具体功能描述我在grid.scss中有解释。
// 我个人猜测有可能是历史保留。
// 生成尺寸为xs的列的样式
@mixin make-xs-column($columns, $gutter: $grid-gutter-width) {
position: relative;
float: left;
width: percentage(($columns / $grid-columns)); // 注① 数字函数percentage(),将一个不带单位的数值转成百分比。
min-height: 1px;
padding-left: ($gutter / 2);
padding-right: ($gutter / 2);
}
@mixin make-xs-column-offset($columns) {
margin-left: percentage(($columns / $grid-columns));
}
@mixin make-xs-column-push($columns) {
left: percentage(($columns / $grid-columns));
}
@mixin make-xs-column-pull($columns) {
right: percentage(($columns / $grid-columns));
}
// 生成尺寸为sm的列的样式
@mixin make-sm-column($columns, $gutter: $grid-gutter-width) {
position: relative;
min-height: 1px;
padding-left: ($gutter / 2);
padding-right: ($gutter / 2);
@media (min-width: $screen-sm-min) { // 当屏幕(浏览器可视区宽度)大于768px时
float: left;
width: percentage(($columns / $grid-columns));
}
}
@mixin make-sm-column-offset($columns) {
@media (min-width: $screen-sm-min) {
margin-left: percentage(($columns / $grid-columns));
}
}
@mixin make-sm-column-push($columns) {
@media (min-width: $screen-sm-min) {
left: percentage(($columns / $grid-columns));
}
}
@mixin make-sm-column-pull($columns) {
@media (min-width: $screen-sm-min) {
right: percentage(($columns / $grid-columns));
}
}
// 生成尺寸为md的列的样式
@mixin make-md-column($columns, $gutter: $grid-gutter-width) {
position: relative;
min-height: 1px;
padding-left: ($gutter / 2);
padding-right: ($gutter / 2);
@media (min-width: $screen-md-min) {
float: left;
width: percentage(($columns / $grid-columns));
}
}
@mixin make-md-column-offset($columns) {
@media (min-width: $screen-md-min) {
margin-left: percentage(($columns / $grid-columns));
}
}
@mixin make-md-column-push($columns) {
@media (min-width: $screen-md-min) {
left: percentage(($columns / $grid-columns));
}
}
@mixin make-md-column-pull($columns) {
@media (min-width: $screen-md-min) {
right: percentage(($columns / $grid-columns));
}
}
// 生成尺寸为lg的列的样式
@mixin make-lg-column($columns, $gutter: $grid-gutter-width) {
position: relative;
min-height: 1px;
padding-left: ($gutter / 2);
padding-right: ($gutter / 2);
@media (min-width: $screen-lg-min) {
float: left;
width: percentage(($columns / $grid-columns));
}
}
@mixin make-lg-column-offset($columns) {
@media (min-width: $screen-lg-min) {
margin-left: percentage(($columns / $grid-columns));
}
}
@mixin make-lg-column-push($columns) {
@media (min-width: $screen-lg-min) {
left: percentage(($columns / $grid-columns));
}
}
@mixin make-lg-column-pull($columns) {
@media (min-width: $screen-lg-min) {
right: percentage(($columns / $grid-columns));
}
}

grid-frameword.scss(mixins)

源文:

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// 栅格框架布局生成
//
// bs栅格布局里列样式的形成:列的个数是通过变量`$grid-columns`的值来决定。
// 在less里明确定义这种方法是递归,而sass支持真正的循环。
@mixin make-grid-columns($i: 1, $list: ".col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}") {
@for $i from (1 + 1) through $grid-columns {
$list: "#{$list}, .col-xs-#{$i}, .col-sm-#{$i}, .col-md-#{$i}, .col-lg-#{$i}";
}
#{$list} {
position: relative;
// 防止空内容的列引起页面塌陷
min-height: 1px;
// 用于列与内容之间的间隔
padding-left: ($grid-gutter-width / 2);
padding-right: ($grid-gutter-width / 2);
}
}
// 在less里明确定义这种方法是递归,而sass支持真正的循环。
@mixin float-grid-columns($class, $i: 1, $list: ".col-#{$class}-#{$i}") {
@for $i from (1 + 1) through $grid-columns {
$list: "#{$list}, .col-#{$class}-#{$i}";
}
#{$list} {
float: left;
}
}
@mixin calc-grid-column($index, $class, $type) {
@if ($type == width) and ($index > 0) {
.col-#{$class}-#{$index} {
width: percentage(($index / $grid-columns));
}
}
@if ($type == push) and ($index > 0) {
.col-#{$class}-push-#{$index} {
left: percentage(($index / $grid-columns)); // 设置列向右偏移
}
}
@if ($type == push) and ($index == 0) {
.col-#{$class}-push-0 {
left: auto;
}
}
@if ($type == pull) and ($index > 0) {
.col-#{$class}-pull-#{$index} {
right: percentage(($index / $grid-columns)); // 设置列向左偏移
}
}
@if ($type == pull) and ($index == 0) {
.col-#{$class}-pull-0 {
right: auto;
}
}
@if ($type == offset) {
.col-#{$class}-offset-#{$index} {
margin-left: percentage(($index / $grid-columns)); // 设置列向右偏移
}
}
}
// 在less里明确定义这种方法是递归,而sass支持真正的循环。
@mixin loop-grid-columns($columns, $class, $type) { // (eg:12 ,xs,width)
@for $i from 0 through $columns {
@include calc-grid-column($i, $class, $type);
}
}
// 建立布局的具体样式
@mixin make-grid($class) {
@include float-grid-columns($class); // 给布局框架里的列添加float:left属性值
@include loop-grid-columns($grid-columns, $class, width); // 给布局框架里的列设置指定的宽度
@include loop-grid-columns($grid-columns, $class, pull); // 给布局框架里的列设置指定的偏移百分比(向左)
@include loop-grid-columns($grid-columns, $class, push);// 给布局框架里的列设置指定的偏移百分比(向右)
@include loop-grid-columns($grid-columns, $class, offset);// 给布局框架里的列设置指定的外边距百分比(向右)
}

相关说明

  • 注①:数字函数 percentage() 将一个不带单位的数值转成百分比。
    • width: percentage(.5) ==> width: 50%;
    • width: percentage(.1rem / .3rem) ==> width: 33.33333%;

      知识点

  • sass @for函数
  • css 属性选择器,这个选择器是我在比对代码中发现自己曾经忽略的css知识点。个人认为合理利用属性选择器能够写出更语义更简洁高效的css样式。