你可能已經(jīng)聽(tīng)說(shuō)了一個(gè)“大新聞”:Bootstrap4 合并了代號(hào)為#21389的PR某抓,宣布放棄支持IE9迄损,并默認(rèn)使用flexbox彈性盒模型布局坑质。
這標(biāo)志著:
1)前端開(kāi)發(fā)全面步入“現(xiàn)代瀏覽器”的時(shí)代進(jìn)一步來(lái)臨患雇;
2)樣式處理也再一次面向未來(lái)妈经,擁抱更加靈活的彈性盒模型-Flex布局淮野。
這篇文章會(huì)帶你深入Bootstrap最新版源碼,窺探其架構(gòu)組織奧秘吹泡,并解析最具亮點(diǎn)的柵格化系統(tǒng)骤星。
同時(shí),你也會(huì)了解到sass的高階用法和flex最新語(yǔ)法的奧秘爆哑。
BS4的新特性
在開(kāi)啟我們的探索之前洞难,有必要先梳理一下BS4添加的新特性:
1)從Less遷移到Sass:
現(xiàn)在,Bootstrap已加入Sass的大家庭中揭朝。得益于Libsass(Sass 解析器)队贱,Bootstrap的編譯速度比以前更快;
2)改進(jìn)網(wǎng)格系統(tǒng):
新增一個(gè)網(wǎng)格層適配移動(dòng)設(shè)備潭袱,并整頓語(yǔ)義混合柱嫌。
3)默認(rèn)彈性盒模型(flexbox):
這是項(xiàng)劃時(shí)代的變動(dòng),利用flexbox的優(yōu)勢(shì)快速布局屯换。
4)廢棄了wells编丘、thumbnails和panels,使用cards代替彤悔。
5)新的自定義選項(xiàng):
不再像上個(gè)版本一樣嘉抓,將漸變、淡入淡出晕窑、陰影等效果分放在單獨(dú)的樣式表中抑片。而是將所有選項(xiàng)都移到一個(gè)Sass變量中。
6)使用rem和em單位杨赤。
7)重構(gòu)所有JavaScript插件:
Bootstrap 4用ES6重寫(xiě)了所有插件〕ㄕ現(xiàn)在提供UMD支持、泛型拆解方法望拖、選項(xiàng)類型檢查等特性渺尘。
8)改進(jìn)工具提示和popovers自動(dòng)定位:
這部分要感謝Tether(A positioning engine to make overlays, tooltips and dropdowns better)工具的幫助,
如果你還不知道Tether是什么说敏,可以去他家Github地址了解一下鸥跟,源碼也短小精悍,值得一讀。
BS4柵格系統(tǒng)揭秘
了解了以上新特性医咨,我們主要研究BS從誕生以來(lái)最大的“賣點(diǎn)” — 柵格系統(tǒng)枫匾。
一個(gè)柵格實(shí)例
我們選取代表性的BS4官網(wǎng)范例,可以在線參考, 或者參看以下截圖拟淮,
在寬屏幕下干茉,我們看到:
當(dāng)屏幕寬度小于576px時(shí)候,我們有:
對(duì)應(yīng)代碼:
<div class="col-6 col-sm-3">
...
</div>
<div class="col-6 col-sm-3">
...
</div>
<div class="col-6 col-sm-3">
...
</div>
<div class="col-6 col-sm-3">
...
</div>
.col-6 class樣式在源碼里面可以簡(jiǎn)單歸納(不完全)為:
.col-6 {
-webkit-box-flex: 0;
-webkit-flex: 0 0 50%;
-ms-flex: 0 0 50%;
flex: 0 0 50%;
max-width: 50%;
}
.col-sm-3 class在源碼里面可以歸納為:
.col-sm-3{
-webkit-box-flex: 0;
-webkit-flex: 0 0 25%;
-ms-flex: 0 0 25%;
flex: 0 0 25%;
max-width: 25%;
}
兩種類的共存和交替作用
我們看到很泊,代碼里設(shè)置了這兩個(gè)class進(jìn)行樣式聲明角虫,很明顯他們的樣式屬性是有沖突的,那么他們是如何做到“和平共處”交替發(fā)揮作用的呢委造?
1)在屏幕寬度大于576px時(shí)候戳鹅,我們發(fā)現(xiàn).col-sm-3并沒(méi)有起作用,這時(shí)候起作用的是.col-6昏兆。
我們?cè)谠创a里發(fā)現(xiàn).col-sm-的樣式聲明全部在@media (min-width: 576px) {...}的媒體查詢中枫虏,
這就保證了在576px寬度以上的屏幕,只有在媒體查詢之外的.col-樣式聲明發(fā)揮了作用爬虱。
2)在屏幕寬度小于576px時(shí)候隶债,命中媒體查詢,命中.col-sm-3的樣式聲明跑筝。他的優(yōu)先級(jí)一定大于.col-6(媒體查詢優(yōu)先級(jí)高)死讹,這時(shí)候就保證了移動(dòng)端的樣式“占上風(fēng)”。
flex講解
從上面樣式代碼里看到類似flex: 0 0 25%的聲明继蜡,為了理解它回俐,我們從flex屬性入手:
flex屬性是flex-grow, flex-shrink 和 flex-basis的簡(jiǎn)寫(xiě)(類似backgroud是很多背景屬性的簡(jiǎn)寫(xiě)一樣),
它的默認(rèn)值為0 1 auto稀并。后兩個(gè)屬性可選仅颇。語(yǔ)法格式如下:
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
1)flex-grow:屬性定義項(xiàng)目的放大比例,默認(rèn)為0碘举。我們看到BS代碼里這個(gè)值一直為0忘瓦,即如果存在剩余空間,也不放大引颈。
2)flex-shrink:屬性定義了項(xiàng)目的縮小比例耕皮,默認(rèn)為1,即如果空間不足蝙场,該項(xiàng)目將縮小凌停。
3)flex-basis:屬性定義了在分配多余空間之前,項(xiàng)目占據(jù)的主軸空間(main size)售滤。
瀏覽器根據(jù)這個(gè)屬性罚拟,計(jì)算主軸是否有多余空間台诗。它可以設(shè)為跟width或height屬性一樣的值(比如350px),則項(xiàng)目將占據(jù)固定空間赐俗。
當(dāng)然BS4這里設(shè)置為比例值拉队,這也是響應(yīng)式自然而然實(shí)現(xiàn)的基礎(chǔ)。
SASS在BS4工程化中的偉大作用
看到此阻逮,不難明白BS4柵格是如何實(shí)現(xiàn)的粱快,但是這并不是此文的最終目的。我們可以深入更多:比如叔扼,BS4的柵格系統(tǒng)里事哭,一行一共是12欄。他的媒體查詢斷點(diǎn)又包括:xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px币励。
我們會(huì)想組織生成如此大量的CSS樣式慷蠕,不用預(yù)處理器簡(jiǎn)直是反人類的珊拼。而B(niǎo)S4卻是把sass用到了極致食呻。
參考其源碼dist/css目錄下樣式代碼,我們進(jìn)行分析:
.col-sm-*是如何生成的
我們深入其scss目錄下澎现,scss/mixins/_grid.scss文件:
@if $enable-grid-classes {
@include make-grid-columns();
}
在enable-grid-classes變量為true的情況下(默認(rèn)為true)仅胞,調(diào)用make-grid-columns,make-grid-columns()這個(gè)mixin定義在scss/mixins/_grid-reamework.scss文件中(找的我好心累剑辫。干旧。。):
@mixin make-grid-columns($columns: $grid-columns, $gutters: $grid-gutter-widths, $breakpoints: $grid-breakpoints) {
...
}
這個(gè)mixin接受三個(gè)參數(shù):
1)$columns表示柵格數(shù)目妹蔽,默認(rèn)為12椎眯;
2)$gutters默認(rèn)為30
3)$breakpoints表示斷點(diǎn)設(shè)置,這是一個(gè)全局變量胳岂,為map類型编整。
這些你可以在scss/mixins/_breakpoints.scss文件中和scss/_variables.scss文件中找到。
認(rèn)識(shí)了這些參數(shù)乳丰,我們看.col-sm-具體實(shí)現(xiàn)掌测,下面代碼我已經(jīng)進(jìn)行過(guò)大范圍精簡(jiǎn),只保留col-sm-相關(guān)部分产园,并且加了注釋:
@each $breakpoint in map-keys($breakpoints) {
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront.
$infix: breakpoint-infix($breakpoint, $breakpoints);
// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
// Makes the @content apply to the given breakpoint and wider.
@include media-breakpoint-up($breakpoint, $breakpoints) {
@for $i from 1 through $columns {
.col#{$infix}-#{$i} {
@include make-col($i, $columns);
}
}
}
}
我們一步一步來(lái)分析:
1)@each $breakpoint in map-keys($breakpoints)汞斧,對(duì)每一個(gè)斷點(diǎn)進(jìn)行遍歷;
2)breakpoint-infix是一個(gè)函數(shù)什燕,它定義在css/mixins/_breakpoints.scss文件當(dāng)中粘勒, 返回一個(gè)帶破折號(hào)的斷點(diǎn)標(biāo)識(shí)字符串,比如這里我們關(guān)系的就是“-sm”屎即;
3)media-breakpoint-up是一個(gè)mixin:
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
@if $min {
@media (min-width: $min) {
@content;
}
} @else {
@content;
}
}
4)breakpoint-min又是一個(gè)函數(shù)庙睡,它返回了斷點(diǎn)的具體數(shù)值。這里是用來(lái)拼媒體查詢條件的。
5)最后最關(guān)鍵樣式的生成又使用了另外一個(gè)定義在css/mixins/_grid.scss文件當(dāng)中的mixin:
@mixin make-col($size, $columns: $grid-columns) {
flex: 0 0 percentage($size / $columns);
max-width: percentage($size / $columns);
}
到此為止埃撵,我們深入了Bootstrap V4的scss/目錄下的源碼赵颅,研究涉及了:
css/mixins/_grid-framework.scss文件;
css/mixins/_breakpoints.scss文件;
css/mixins/_grid.scss文件;
css/_variables.scss文件;
css/bootstrap-gris.scss文件;
......
如果你理解了這些,那么再去讀bootstrap新版源碼就不會(huì)存在任何難度暂刘。相信你也能夠在全局上饺谬,以“上帝視角”了解sass所起的作用,大型樣式框架的架構(gòu)組織谣拣。
總結(jié)
通過(guò)閱讀源碼的柵格系統(tǒng)部分募寨,我們應(yīng)該認(rèn)識(shí)到sass對(duì)于這樣大型樣式框架系統(tǒng)的重要意義:
1)css模塊化在管理組織上的靈活性;
2)復(fù)用的意義:使用了大量的mixin,function,全局變量森缠;
3)像JS一樣神奇的語(yǔ)法拔鹰,包括條件、遍歷等等等等贵涵。
同時(shí)列肢,你也應(yīng)該對(duì)flex這一神器有了更加深刻的認(rèn)識(shí)。