深入新版BS4源碼 探索flex和工程化sass奧秘
你可能已經聽說了一個「大新聞」:Bootstrap4 合併了代號為#21389的PR,宣布放棄支持IE9,並默認使用flexbox彈性盒模型。
這標誌著前端開發全面步入「現代瀏覽器」的時代進一步來臨;樣式處理也再一次面向未來,擁抱更加靈活的彈性盒模型-Flex布局。這篇文章會帶你深入Bootstrap最新版源碼,窺探其架構組織奧秘,並解析最具亮點的柵格化系統。
你也會了解到sass的高階用法和flex最新語法奧秘。BS4的新特性
在開啟我們的探索之前,有必要先梳理一下BS4添加的新特性:
1)從Less遷移到Sass:
現在,Bootstrap已加入Sass的大家庭中。得益於Libsass(Sass 解析器),Bootstrap的編譯速度比以前更快;2)改進網格系統:新增一個網格層適配移動設備,並整頓語義混合。3)默認彈性盒模型(flexbox):這是項劃時代的變動,利用flexbox的優勢快速布局。4)廢棄了wells、thumbnails和panels,使用cards代替。5)新的自定義選項:不再像上個版本一樣,將漸變、淡入淡出、陰影等效果分放在單獨的樣式表中。而是將所有選項都移到一個Sass變數中。想要給全局或考慮不到的角落定義一個默認效果?很簡單,只要更新變數值,然後重新編譯就可以了。6)使用rem和em單位。
7)重構所有JavaScript插件:Bootstrap 4用ES6重寫了所有插件。現在提供UMD支持、泛型拆解方法、選項類型檢查等特性。8)改進工具提示和popovers自動定位:這部分要感謝Tether(A positioning engine to make overlays, tooltips and dropdowns better)工具的幫助,如果你還不知道Tether是什麼,可以去他家Github地址。BS4柵格系統揭秘
了解了以上新特性,我們主要研究BS從誕生以來最大的「賣點」-柵格系統。
一個柵格實例
我們選取代表性的BS4官網範例,可以在線參考, 或者參看以下截圖,
在大屏幕下,我們看到:當屏幕寬度小於576px時候,我們有:
對應代碼:
<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表示柵格數目默認為122)$gutters默認為303)$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這一神器有了更加深刻的認識。本文作者:留學法國的帥哥,國家二級運動員,百度高級FE,快來關注 Lucas HC - 知乎
原文鏈接:深入新版BS4源碼 探索flex和工程化sass奧秘
微信公眾號
關注微信公眾號:顏海鏡,最新博文優先推送,不再錯過精彩內容。
推薦閱讀:
※css 預處理器實現 css最佳實踐的 最佳實踐是什麼?
※點點網是出於什麼目的選擇使用 LESS?LESS 相對於傳統的 CSS 的優勢是什麼?
※CSS 的預處理程序(Sass、LESS、Stylus 等)分別都有哪些優缺點?
※css命名長度對查找效率有影響嗎?
TAG:CSS | BootstrapTwitter | Less |