深刻新版BS4源碼 探索flex和工程化sass奧祕

你可能已經據說了一個「大新聞」:Bootstrap4 合併了代號爲#21389的PR,宣佈放棄支持IE9,並默認使用flexbox彈性盒模型
這標誌着:
1)前端開發全面步入「現代瀏覽器」的時代進一步來臨;
2)樣式處理也再一次面向將來,擁抱更加靈活的彈性盒模型-Flex佈局。css

這篇文章會帶你深刻Bootstrap最新版源碼,窺探其架構組織奧祕,並解析最具亮點的柵格化系統。
同時,你也會了解到sass的高階用法和flex最新語法的奧祕。前端

BS4的新特性

在開啓咱們的探索以前,有必要先梳理一下BS4添加的新特性:
1)從Less遷移到Sass:
如今,Bootstrap已加入Sass的你們庭中。得益於Libsass(Sass 解析器),Bootstrap的編譯速度比之前更快;git

2)改進網格系統:
新增一個網格層適配移動設備,並整頓語義混合。github

3)默認彈性盒模型(flexbox):
這是項劃時代的變更,利用flexbox的優點快速佈局。web

4)廢棄了wells、thumbnails和panels,使用cards代替。bootstrap

5)新的自定義選項:
再也不像上個版本同樣,將漸變、淡入淡出、陰影等效果分放在單獨的樣式表中。而是將全部選項都移到一個Sass變量中。
想要給全局或考慮不到的角落定義一個默認效果?很簡單,只要更新變量值,而後從新編譯就能夠了。瀏覽器

6)使用rem和em單位。sass

7)重構全部JavaScript插件:
Bootstrap 4用ES6重寫了全部插件。如今提供UMD支持、泛型拆解方法、選項類型檢查等特性。架構

8)改進工具提示和popovers自動定位:
這部分要感謝Tether(A positioning engine to make overlays, tooltips and dropdowns better)工具的幫助,
若是你還不知道Tether是什麼,能夠去他家Github地址app

BS4柵格系統揭祕

瞭解了以上新特性,咱們主要研究BS從誕生以來最大的「賣點」-柵格系統。

一個柵格實例

咱們選取表明性的BS4官網範例,能夠在線參考, 或者參看如下截圖,
在寬屏幕下,咱們看到:

寬屏幕狀態下

當屏幕寬度小於576px時候,咱們有:

iphone5屏幕下

對應代碼:

<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樣式在源碼裏面能夠簡單概括(不徹底)爲:

.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%;
}

兩種類的共存和交替做用

咱們看到,代碼裏設置了這兩個class進行樣式聲明,很明顯他們的樣式屬性是有衝突的,那麼他們是如何作到「和平共處」交替發揮做用的呢?

1)在屏幕寬度小於576px時候,咱們發現.col-sm-3並無起做用,這時候起做用的是.col-6。
咱們在源碼裏發現.col-sm-*的樣式聲明所有在@media (min-width: 576px) {...}的媒體查詢中,
這就保證了在576px如下屏幕,只有在媒體查詢以外的.col-*樣式聲明發揮了做用。
2)在屏幕寬度大於576px時候,命中.col-sm-3的樣式聲明,全部他的優先級必定大於.col-6,這時候就保證了一行四欄的樣式「佔上風」。

flex講解

咱們從樣式代碼裏看到相似flex: 0 0 25%的聲明,爲了理解它,咱們從flex屬性入手:
flex屬性是flex-grow, flex-shrink 和 flex-basis的簡寫(相似backgroud是不少背景屬性的簡寫同樣),
它的默認值爲0 1 auto。後兩個屬性可選。語法格式以下:

.item {
    flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

1)flex-grow:屬性定義項目的放大比例,默認爲0。咱們看到BS代碼裏這個值一直爲0,即若是存在剩餘空間,也不放大。

2)flex-shrink:屬性定義了項目的縮小比例,默認爲1,即若是空間不足,該項目將縮小。

3)flex-basis:屬性定義了在分配多餘空間以前,項目佔據的主軸空間(main size)。
瀏覽器根據這個屬性,計算主軸是否有多餘空間。它能夠設爲跟width或height屬性同樣的值(好比350px),則項目將佔據固定空間。
固然BS4這裏設置爲比例值,這也是響應式天然而然實現的基礎。

SASS在BS4工程化中的偉大做用

看到此,不難明白BS4柵格的實現,可是這並非此文的最終目的。咱們能夠深刻更多,好比,BS4的柵格系統裏,一行一共是12欄。他的媒體查詢斷點又包括:xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px。
參考其源碼dist/css目錄下樣式代碼,咱們會想組織生成如此大量的CSS樣式,不用預處理器簡直是反人類的。而BS4倒是把sass用到了極致。

.col-sm-*是如何生成的

咱們深刻其scss目錄下,scss/mixins/_grid.scss文件:

@if $enable-grid-classes {
    @include make-grid-columns();
}

在enable-grid-classes變量爲true的狀況下(默認爲true),調用make-grid-columns()

make-grid-columns()這個mixin定義在scss/mixins/_grid-reamework.scss文件中(找的我好心累。。。):

@mixin make-grid-columns($columns: $grid-columns, $gutters: $grid-gutter-widths, $breakpoints: $grid-breakpoints) {
    ...
}

這個mixin接受三個參數:
1)$columns表示柵格數目默認爲12
2)$gutters默認爲30
3)$breakpoints表示斷點設置,這是一個全局變量,爲map類型。
這些你能夠在scss/mixins/_breakpoints.scss文件中和scss/_variables.scss文件中找到。

認識了這些參數,咱們看.col-sm-具體實現,下面代碼我已經進行過大範圍精簡,只保留col-sm-相關部分,而且加了註釋:

@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);
            }
        }
    }
}

咱們一步一步來分析:
1)@each $breakpoint in map-keys($breakpoints),對每個斷點進行遍歷;
2)breakpoint-infix是一個函數,它定義在css/mixins/_breakpoints.scss文件當中, 返回一個帶破折號的斷點標識字符串,好比這裏咱們關係的就是「-sm」;
3)media-breakpoint-up是一個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又是一個函數,它返回了斷點的具體數值。這裏是用來拼媒體查詢條件的。
5)最後最關鍵樣式的生成又使用了另一個定義在css/mixins/_grid.scss文件當中的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新版源碼就不會存在任何難度。相信你也可以在全局上,以「上帝視角」瞭解sass所起的做用,大型樣式框架的架構組織。

總結

經過閱讀源碼的柵格系統部分,咱們應該認識到sass對於這樣大型樣式框架系統的重要意義:1)css模塊化在管理組織上的靈活性;2)複用的意義,咱們使用了大量的mixin,function,全局變量;3)像JS同樣神奇的語法,包括條件、遍歷等等等等。咱們也應該對flex這一神器有了更加深入的認識。

相關文章
相關標籤/搜索