BootStrap栅格系统的源码分析

it2026-03-17  5

文章目录

容器公共样式 container-fixed清除浮动 .clearfix 流体容器固定容器源码分析 栅格系统行 & 列.make-row.列make-grid-columns().make-grid(xs); 栅格盒模型的设计精妙之处

容器

公共样式 container-fixed

【固定容器和流体容器的公共样式】

/** grid.less **/ .container-fixed(@gutter: @grid-gutter-width) { margin-left: auto; margin-right: auto; padding-left: floor((@gutter / 2)); // 槽宽的一半:即 30px / 2 = 15px padding-rigth: ceil((@gutter / 2)); &:extend(.clearfix all) // 清除浮动,继承clearfix.less里面定义的clearfix混合 }

清除浮动 .clearfix

/** clearfix.less **/ // BootStrap .clearfix(){ &:before, &:after { content: " "; display: table; // 兼容性比较高 } &:after { clear: both; } }

【常见用来清除浮动的几种方式】

给浮动元素的父盒子添加伪元素,并利用伪元素来清除浮动

.clearfix::after{ content: ""; dispaly: block; clear: both; visibility:hidden; height:0; zoom:1 // 解决ie6,7的浮动问题 }

给浮动元素的父级盒子添加overflow:auto或overflow:hidden(不推荐使用)

overflow:auto=> 如果页面中需要出现滚动条可以使用

overflow:hidden=> 页面不需要滚动条,没有使用position(超出的尺寸会被隐藏)可以使用

父级元素也浮动(了解)

给浮动的父元素添加display:table,将其变成表格(不推荐使用)

流体容器

盒子的width为auto

固定容器

阈值width>= 1200【lg:大屏PC】1170[ 992, 1200 ) 【md:中屏PC】970[ 768, 992 ) 【sm:平板】750<= 768【xs:手机】auto (流体容器)

【width:100%和width:auto的区别】

width:100%: 左右的padding是在两边另外加的width:auto: 左右的padding是里面扣掉的

width:auto

width:100%

源码分析

【固定容器的样式】:

.container{ // 公共样式 .container-fixed(); /** 媒体查询:通过媒体查询,来设置不同屏幕尺寸下的网页宽度 阈值: @screen-sm-min : 768px @screen-md-min : 992px @screen-lg-min : 1200px width: @container-sm = 720px + @grid-gutter-width = 750px @container-md = 940px + @grid-gutter-width = 970px @container-lg = 1140px + @grid-gutter-width = 1170px **/ @media (min-width: @screen-sm-min) { width: @container-sm; // 750px } @media (min-width: @screen-md-min) { // width: @container-md; // 970px } @media (min-width: @screen-lg-min) { width: @container-lg; // 1170px } }

假设目前屏幕是 1300px前面的两条样式也会被读到,只不过是被最后一个满足条件的样式覆盖了

假设屏幕是 200px则这三条样式都不会被读到,因此此时就是用默认值:width: auto

栅格系统

栅格系统是通过一系列的行和列的组合来创建页面布局的。

行 & 列

.make-row

.make-row(@gutter: @grid-gutter-width){ margin-left: ceil((@gutter / -2)); // 负槽宽的一半即: -15px margin-right: floor((@gutter / -2)); // 负槽宽的一半即: -15px &:extend(.clearfix all) }

.列

.make-grid-columns(); // 默认 手机: xm .make-grid(xs); // 平板:sm @media (min-width: @screen-sm-min) { .make-grid(sm); } // 中屏PC md @media (min-width: @screen-md-min) { .make-grid(md); } // 大屏PC lg @media (min-width: @screen-lg-min) { .make-grid(lg); }

make-grid-columns()

列的第一步:给不同屏幕尺寸下的每一个都设置一个共同的样式:相对定位,列的最小高度,左右padding

/** make-grid-columns() 混合的内容**/ make-grid-columns(){ .col(@index){ @item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}"; .col((@index + 1), @item); } .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}"); } .col(@index, @list) when (@index > @grid-columns) { @{list} { position: relative; // 为了列排序做准备 min-height: 1px; padding-left: ceil((@grid-gutter-width / 2)); padding-right: floor((@grid-gutter-width / 2)) } } .col(1); }

.make-grid(xs);

列的第二步:根据屏幕不同的尺寸大小,来执行.make-grid(type)混合

.make-grid(xs); // 平板:sm @media (min-width: @screen-sm-min) { .make-grid(sm); } // 中屏PC md @media (min-width: @screen-md-min) { .make-grid(md); } // 大屏PC lg @media (min-width: @screen-lg-min) { .make-grid(lg); }

【第 2 步】

.make-grid(@class){ .float-grid-columns(@class); // 第 2.1 步 .loop-grid-columns(@grid-columns, @class, width); // 第 2.2 步 .loop-grid-columns(@grid-columns, @class, pull); // 第 2.3 步 .loop-grid-columns(@grid-columns, @class, push); // 第 2.3 步 .loop-grid-columns(@grid-columns, @class, offset); // 第 2.4 步 }

【第 2.1 步】

给每一个列都设置浮动

.float-grid-columns(@class) { .col(@index){ @item: ~".col-@{class}-@{index}"; .col((@index+1), @item); } .col(@index, @list) when (@index =< @grid-columns) { @item: ~".col-@{class}-@{index}"; .col((@index+1), ~"@{list}, @{item}") } .col(@index, @list) when (@index > @grid-columns) { @{list} { float: left; } } .col(1) }

编译后的结果:(加入当前设备是 xs)

.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{ float: left; }

【第 2.2、2.3、2.4 入口】

.loop-grid-columns(@grid-columns, @class, width); // 第 2.2 步 .loop-grid-columns(@grid-columns, @class, pull); // 第 2.3 步 .loop-grid-columns(@grid-columns, @class, push); // 第 2.3 步 .loop-grid-columns(@grid-columns, @class, offset); // 第 2.4 步 // 2.2、 2.3、 2.4 入口 .loop-grid-columns(@index, @class, @type) when(@index >= 0) { // 相当于递归体(要被调用12次) .calc-grid-columns(@index, @class, @type); // 下一次循环 .loop-grid-columns((@index-1), @class, @type) }

【第 2.2 步】

/**根据列的个数设置对应的宽度 (作为递归体,要被调用12次)**/ .calc-grid-columns(@index, @class, @type) when (@type = width) and (@index > 0) { .col-@{class}-@{index}{ width: percentage((@index / @grid-columns)); } } .loop-grid-columns((@index-1), @class, @type)

假设这里的type为 xs:步骤2.2编译后的结果为:

.col-xs-12{ width: 12/12; } .col-xs-12{ width: 11/12; } ... .col-xs-1{ width: 1/12; }

栅格的组合就是通过less的递归来实现的

<div calss= "container"> <div class="col-lg-10 col-md-6"></div> <div class="col-lg-2 col-md-6"></div> </div>

【第 2.3 步】列排序(设置列的left和right)

.loop-grid-columns(@index, @class, @type) when(@index >= 0) { // 相当于递归体(要被调用12次) .calc-grid-columns(@index, @class, @type); // 下一次循环 .loop-grid-columns((@index-1), @class, @type) } /**作为递归体,要被调用12次**/ .calc-grid-columns(@index, @class, @type) when (@type = push) and (@index > 0) { .col-@{class}-push-@{index}{ left: percentage((@index / @grid-columns)) } } /**执行一次**/ .cal-grid-columns(@index, @class, @type) when (@type = push) and (@index = 0) { .col-@{class}-push-0 { left: auto; } } .loop-grid-columns((@index-1), @class, @type) push => left, 且 index=0时, left:autopull => right, 且 index=0时, right: 0 /**作为递归体,要被调用12次**/ .calc-grid-columns(@index, @class, @type) when (@type = pull) and (@index > 0) { .col-@{class}-pull-@{index}{ right: percentage((@index / @grid-columns)) } } /**执行一次**/ .cal-grid-columns(@index, @class, @type) when (@type = pull) and (@index = 0) { .col-@{class}-pull-0 { right: 0; } } .loop-grid-columns((@index-1), @class, @type)

2.3编译的结果:

/**push**/ .col-xs-push-12{ left: 12/12; } .col-xs-push-12{ left: 11/12; } ... .col-xs-push-1{ left: 1/12; } //注意 .col-xs-push-0{ left: auto; } /**pull**/ .col-xs-pull-12{ right: 12/12; } .col-xs-pull-12{ right: 11/12; } ... .col-xs-pull-1{ right: 1/12; } //注意 .col-xs-pull-0{ right: 0; }

【第 2.4 步】列偏移

.loop-grid-columns(@index, @class, @type) when(@index >= 0) { // 相当于递归体(要被调用12次) .calc-grid-columns(@index, @class, @type); // 下一次循环 .loop-grid-columns((@index-1), @class, @type) } // 执行12次 .cal-grid-columns(@index, @class, @type) when (@type = offset){ .col-@{class}-offset-@{index}{ margin-left: percentage((@index / @grid-columns)) } } .loop-grid-columns((@index-1), @class, @type)

编译结果:

/**offset**/ .col-xs-offset-12{ margin-left: 12/12; } .col-xs-offset-12{ margin-left: 11/12; } ... .col-xs-offset-1{ margin-left: 1/12; } .col-xs-offset-0{ margin-left: 0; }

栅格盒模型的设计精妙之处

定制化:p13

最新回复(0)