文章目录
前言
Bootstrap3依赖于jQuery,须先引入jQuery后方可使用。 Bootstrap3源码涉及Less,建议先了解Less再阅读源码。官网:https://www.bootcss.com/
Git:https://github.com/twbs/bootstrap/
一、Bootstrap和它的栅格系统
1.Bootstrap介绍
Bootstrap是快速开发Web应用程序的前端工具包。它是一个HTML、CSS和JS的集合。为Web开发者提供了各种版式,如表单、组件、页面内容、布局等。
预处理工具
Bootstrap 的源码是采用最流行的 CSS 预处理工具 Less 和 Sass 开发的。可以直接采用预编译的 CSS 文件快速开发,也可以从 Bootstrap 源码自定义自己需要的样式。
Bootstrap3:Less
Bootstrap4、5:Sass
一个框架、多种设备。
在 Bootstrap 的帮助下通过同一份源码快速、有效地适配手机、平板和 PC 设备,这一切都是 CSS 媒体查询(Media Query)的功劳。
2.容器
- 流体容器:width:auto
流体布局:网页缩放时页面布局会随着浏览器大小而改变。 - 固定容器
阈值 | width |
---|---|
>=1200(lg 大屏pc) | 1170(1140 + 槽宽) |
>=992(md 中屏pc) | 970(940 + 槽宽) |
>=768(sm 平板) | 750(720 + 槽宽) |
<768(xs 移动手机) | auto |
3.栅格系统
Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列。它包含了易于使用的预定义类,还有强大的mixin 用于生成更具语义的布局。
二、栅格系统源码分析
涉及源码文件如下:
- variables.less
- grid.less
- mixin/clearfix.less
- /mixin/grid.less
- /mixin/grid-framework.less
1.固定容器&流体容器 公共样式
源码(Less)如下:
/*
入口文件代码(grid.less)
*/
.container {
/* 调用固定和流体容器的公共样式 */
.container-fixed();
......
}
// 流体容器
.container-fluid {
.container-fixed();
}
/*
混合文件代码(grid.less)
固定和流体容器的公共样式
@grid-gutter-width: 30px;(槽宽)(变量声明文件variables.less)
*/
.container-fixed(@gutter: @grid-gutter-width) {
padding-right: ceil((@gutter / 2));
padding-left: floor((@gutter / 2));
margin-right: auto;
margin-left: auto;
&:extend(.clearfix all); //继承clearfix清除浮动
}
/*
清除浮动(clearfix.less)
*/
.clearfix() {
&:before,
&:after {
display: table; // 2
content: " "; // 1
}
&:after {
clear: both;
}
}
其目的是设置容器的默认样式为:
padding-right: 15px;
padding-left: 15px;
margin-right: auto;
margin-left: auto;
2.固定容器 特定样式
源码如下:
/*
入口文件代码(grid.less)
顺序不可变
媒体查询(默认是移动设备)
*/
.container {
.container-fixed();
/* 媒体查询 */
@media (min-width: @screen-sm-min) {
width: @container-sm;
}
@media (min-width: @screen-md-min) {
width: @container-md;
}
@media (min-width: @screen-lg-min) {
width: @container-lg;
}
}
/*
在variables.less文件中值设置如下:
*/
@screen-sm: 768px;
@screen-sm-min: @screen-sm;
@container-tablet: (720px + @grid-gutter-width);
@container-sm: @container-tablet;
@screen-md: 992px;
@screen-md-min: @screen-md;
@container-desktop: (940px + @grid-gutter-width);
@container-md: @container-desktop;
@screen-lg: 1200px;
@screen-lg-min: @screen-lg;
@container-large-desktop: (1140px + @grid-gutter-width);
@container-lg: @container-large-desktop;
3.行
源码如下:
/*
入口文件代码(grid.less)
*/
.row {
.make-row();
}
/*
混合代码(grid.less)
*/
.make-row(@gutter: @grid-gutter-width) {
margin-right: floor((@gutter / -2));
margin-left: ceil((@gutter / -2));
&:extend(.clearfix all);
}
其目的是设置行的默认样式为:
margin-right: -15px;
margin-left: -15px;
4.列
2.4.1 全部加默认样式
源码如下:
.make-grid-columns();
/* @grid-columns: 12;*/
.make-grid-columns() {
/*
1. 首先执行(@index为1)
@item:.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1
调用.col((@index + 1), @item)。将@index+1和@item传过去
*/
.col(@index) {
@item: ~".col-xs-@{
index}, .col-sm-@{
index}, .col-md-@{
index}, .col-lg-@{
index}";
.col((@index + 1), @item);
}
/*
2. (@index为2)
@item:.col-xs-2, .col-sm-2, .col-md-2, .col-lg-2
递归(自己调用自己),直到@index == 12。
最终@{list}为:
.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1,
.col-xs-2, .col-sm-2, .col-md-2, .col-lg-2,
......
.col-xs-12, .col-sm-12, .col-md-12, .col-lg-12
*/
.col(@index, @list) when (@index =< @grid-columns) {
@item: ~".col-xs-@{
index}, .col-sm-@{
index}, .col-md-@{
index}, .col-lg-@{
index}";
.col((@index + 1), ~"@{
list}, @{
item}");
}
/*
3. (@index为13)
@list:
..col-xs-1, .col-sm-1, .col-md-1, .col-lg-1,
.col-xs-2, .col-sm-2, .col-md-2, .col-lg-2,
......
.col-xs-12, .col-sm-12, .col-md-12, .col-lg-12
添加属性
*/
.col(@index, @list) when (@index > @grid-columns) {
@{
list} {
position: relative;
min-height: 1px;
padding-right: floor((@grid-gutter-width / 2));
padding-left: ceil((@grid-gutter-width / 2));
}
}
.col(1); // kickstart it
}
其目的是给列加默认样式:
.make-grid-columns();
.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1,
.col-xs-2, .col-sm-2, .col-md-2, .col-lg-2,
......
.col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{
position: relative;
min-height: 1px;
padding-right: 15px;
padding-left: 15px;
}
2.4.2 设置列的浮动、宽度和位置
源码如下:
// 移动优先(以此为例进行源码分析)
.make-grid(xs);
// Small grid
@media (min-width: @screen-sm-min) {
.make-grid(sm);
}
// Medium grid
@media (min-width: @screen-md-min) {
.make-grid(md);
}
// Large grid
@media (min-width: @screen-lg-min) {
.make-grid(lg);
}
/* 以移动界面为例,此时class=xs*/
.make-grid(@class) {
// 2.1 左浮动
.float-grid-columns(@class);
// 2.2 列宽
.loop-grid-columns(@grid-columns, @class, width);
// 2.3 左右排序
.loop-grid-columns(@grid-columns, @class, pull);
.loop-grid-columns(@grid-columns, @class, push);
// 2.4列偏移
.loop-grid-columns(@grid-columns, @class, offset);
}
2.4.2.1 左浮动
.float-grid-columns(@class) {
/*
@index初始为1
@item:.col-xs-1
*/
.col(@index) {
@item: ~".col-@{
class}-@{
index}";
.col((@index + 1), @item);
}
/*
递归至@index == 12。(@index为2)
最终@list:.col-xs-1,.col-xs-2, ...... .col-xs-12
*/
.col(@index, @list) when (@index =< @grid-columns) {
@item: ~".col-@{
class}-@{
index}";
.col((@index + 1), ~"@{
list}, @{
item}");
}
/*
(@index为13)
@list:.col-xs-1,.col-xs-2, ...... .col-xs-12
添加属性float
*/
.col(@index, @list) when (@index > @grid-columns) {
@{
list} {
float: left;
}
}
.col(1); // kickstart it 初始化
}
2.4.2.2 列宽
/*
@index=12
递归添加所有的width属性。当@index==0时,不符合calc-grid-column的条件。结束
.col-xs-11{ width: 12/12 }
......
.col-xs-1{ width: 1/12 }
*/
.loop-grid-columns(@index, @class, @type) when (@index >= 0) {
.calc-grid-column(@index, @class, @type);
.loop-grid-columns((@index - 1), @class, @type);
}
/*
添加width属性
.col-xs-12{ width: 12/12 }
*/
.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {
.col-@{
class}-@{
index} {
width: percentage((@index / @grid-columns));
}
}
2.4.2.3 列排序
/*
@index=12
递归添加所有的left属性
.col-xs-push-12{ left: 12/12 }
.col-xs-push-11{ left: 11/12 }
......
.col-xs-push-1{ left: 1/12 }
.col-xs-push-0{ left: auto }
*/
.loop-grid-columns(@index, @class, @type) when (@index >= 0) {
.calc-grid-column(@index, @class, @type);
.loop-grid-columns((@index - 1), @class, @type);
}
/*
@index > 0 添加属性left并设置值
*/
.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {
.col-@{
class}-push-@{
index} {
left: percentage((@index / @grid-columns));
}
}
/*
@index == 0 添加属性left并设置值为auto
*/
.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {
.col-@{
class}-push-0 {
left: auto;
}
}
/*
@index=12
递归添加所有的left属性
.col-xs-pull-12{ right: 12/12 }
.col-xs-pull-11{ right: 11/12 }
......
.col-xs-pull-1{ right: 1/12 }
.col-xs-pull-0{ right: auto }
*/
.loop-grid-columns(@index, @class, @type) when (@index >= 0) {
.calc-grid-column(@index, @class, @type);
.loop-grid-columns((@index - 1), @class, @type);
}
/*
@index > 0 添加属性right并设置值
*/
.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {
.col-@{
class}-pull-@{
index} {
right: percentage((@index / @grid-columns));
}
}
/*
@index == 0 添加属性right并设置值为auto
*/
.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {
.col-@{
class}-pull-0 {
right: auto;
}
}
2.4.2.4 列偏移
/*
@index=12
递归添加所有的 margin-left 属性
.col-xs-offset-12{ margin-left: 12/12 }
.col-xs-offset-11{ margin-left: 11/12 }
......
.col-xs-offset-1{ margin-left: 1/12 }
.col-xs-offset-0{ margin-left: auto }
*/
.loop-grid-columns(@index, @class, @type) when (@index >= 0) {
.calc-grid-column(@index, @class, @type);
.loop-grid-columns((@index - 1), @class, @type);
}
/*
@index >= 0 添加属性margin-left并设置值
*/
.calc-grid-column(@index, @class, @type) when (@type = offset) {
.col-@{
class}-offset-@{
index} {
margin-left: percentage((@index / @grid-columns));
}
}
最终列样式:
.make-grid(xs)
//2.1 左浮动
.float-grid-columns(@class);
.col-xs-1,.col-xs-2, ...... .col-xs-12{
float: left;
}
// 2.2 列宽
.loop-grid-columns(@grid-columns, @class, width);
.col-xs-12{
width: 12/12 }
.col-xs-11{
width: 11/12 }
......
.col-xs-1{
width: 1/12 }
// 2.3 左右排序
.loop-grid-columns(@grid-columns, @class, pull);
.col-xs-pull-12{
right: 12/12 }
.col-xs-pull-11{
right: 11/12 }
......
.col-xs-pull-1{
right: 1/12 }
.col-xs-pull-0{
right: auto }
.loop-grid-columns(@grid-columns, @class, push);
.col-xs-push-12{
left: 12/12 }
.col-xs-push-11{
left: 11/12 }
......
.col-xs-push-1{
left: 1/12 }
.col-xs-push-0{
left: auto }
// 2.4 列偏移
.loop-grid-columns(@grid-columns, @class, offset);
.col-xs-offset-12{
margin-left: 12/12 }
.col-xs-offset-11{
margin-left: 11/12 }
......
.col-xs-offset-1{
margin-left: 1/12 }
.col-xs-offset-0{
margin-left: auto }
三、响应式工具
涉及源码文件如下:
- mixin/responsive-visibility.less
- responsive-utilities.less
源码如下:
/* 首先统一设置为不显示 */
.visible-xs,
.visible-sm,
.visible-md,
.visible-lg {
.responsive-invisibility();
}
.visible-xs-block,
.visible-xs-inline,
.visible-xs-inline-block,
.visible-sm-block,
.visible-sm-inline,
.visible-sm-inline-block,
.visible-md-block,
.visible-md-inline,
.visible-md-inline-block,
.visible-lg-block,
.visible-lg-inline,
.visible-lg-inline-block {
display: none !important;
}
/* 设置在什么宽度下显示 */
.visible-xs {
@media (max-width: @screen-xs-max) {
.responsive-visibility();
}
}
.visible-xs-block {
@media (max-width: @screen-xs-max) {
display: block !important;
}
}
......
/* 设置在什么宽度下不显示 */
.hidden-xs {
@media (max-width: @screen-xs-max) {
.responsive-invisibility();
}
}
......
.responsive-visibility() {
display: block !important;
table& {
display: table !important; }
tr& {
display: table-row !important; }
th&,
td& {
display: table-cell !important; }
}
.responsive-invisibility() {
display: none !important;
}
四、栅格和模型设置的精妙之处
-
容器 两边具有15px的padding
-
行 两边具有-15px的margin
-
列 两边具有15px的padding
1. 为了维护槽宽的规定: 列两边必须有15px的padding 2. 为了能使列嵌套行 行两边必须要有-15px的margin 3. 为了让容器可以包裹住行 容器两边必须要有15px的padding