前言
Bootstrap 的成功不僅在于其簡(jiǎn)單易用,更在于其樣式的規(guī)范性以及 HTML 結(jié)構(gòu)的合理性。但是很多人在使用 Bootstrap 時(shí)只是依照文檔盲目的復(fù)制黏貼,并沒有仔細(xì)考慮每個(gè)類的用處,也沒有考慮 HTML 結(jié)構(gòu)搭建的是否合理。在平時(shí)的工作中,我一直和同事強(qiáng)調(diào),一定要挖掘框架的精髓,盡可能的使用框架本身具有的類實(shí)現(xiàn)布局,幾乎所有的 UI 布局都可以使用框架本身完成而不需要編寫額外的冗余的樣式。本文的目的就是介紹如何使用 Bootstrap 搭建常用的布局,并保證布局具有合理的 HTML 結(jié)構(gòu)。不管是傳統(tǒng)開發(fā),還是使用框架,搭建布局的思想是不會(huì)變的。本文所有案例均以 Bootstrap 3 為例, Bootstrap 4 變化較大,但也基本適用,需要讀者仔細(xì)比對(duì),不可盲目照抄。
合理利用柵格
保證合理嵌套
Bootstrap 柵格類的隨意嵌套是造成 HTML 結(jié)構(gòu)混亂的主要原因,雖然 Bootstrap 的柵格類在隨意嵌套時(shí)并不會(huì)出現(xiàn)嚴(yán)重問題,但會(huì)引發(fā)潛在的問題,對(duì)于細(xì)節(jié)控是無(wú)法容忍的。比如下面的這種常見錯(cuò)誤嵌套:
<div class="row"> <div class="col-md-6"> <div class="col-md-8">.col-md-8</div> <div class="col-md-4">.col-md-4</div> </div> <div class="col-md-6">.col-md-6</div> </div>
表面看并沒有大問題,但是如果將柵格描邊,就會(huì)看出不同,見下面的 CodePen:
See the Pen Bootstrap-demo by Zongbin (@nzbin) on CodePen.
我們必須明白每個(gè) Bootstrap 柵格類的作用。其中 .row 和 .col-* 必須要搭配使用,缺一不可,因?yàn)?nbsp;.row 是為了抵消 .col-* 的 margin 負(fù)值,所以并不是可有可無(wú)的類。所以,上面例子的正確結(jié)構(gòu)如下:
<div class="row"> <div class="col-md-6"> <div class="row"> <div class="col-md-8">.col-md-8</div> <div class="col-md-4">.col-md-4</div> </div> </div> <div class="col-md-6">.col-md-6</div> </div>
這是我工作過(guò)程中見過(guò)的最多的一種錯(cuò)誤,必須格外注意。
靈活利用柵格偏移
柵格的列偏移 .col-{breakpoint}-offset-* 應(yīng)該也算是比較常用的布局類,但是我們往往忽視它在大塊版面布局的作用。舉個(gè)例子,比如一個(gè)登錄框在右側(cè)的登錄頁(yè)面:
對(duì)于表單在右側(cè)的布局,實(shí)現(xiàn)方式有很多,比如單獨(dú)使用 float 實(shí)現(xiàn)偏移,或者使用絕對(duì)/相對(duì)定位實(shí)現(xiàn)。但是更好的方式應(yīng)該是使用柵格的列偏移實(shí)現(xiàn),因?yàn)闁鸥裰С猪憫?yīng)式布局。
以下是響應(yīng)式登錄頁(yè)的例子:
See the Pen Bootstrap-demo by Zongbin (@nzbin) on CodePen.
建議在 CodePen 中打開查看效果,因?yàn)槲业牟┛蛢?nèi)容區(qū)較窄,所以只能看到響應(yīng)式布局的小屏斷點(diǎn)。
雖然柵格布局很好,但在工作中一定要謹(jǐn)慎使用,因?yàn)楹芏嗖欢岸说脑O(shè)計(jì)師或產(chǎn)品會(huì)對(duì)前端人員吹毛求疵,這樣的話也只能根據(jù)具體要求做一些調(diào)整了。
水平表單排列
表單中的橫向柵格布局非常常見,Bootstrap 官網(wǎng)也給出了案例,但是對(duì)于多列的橫向表單布局會(huì)稍顯復(fù)雜,過(guò)多的柵格嵌套讓人抓狂。但是只要記住一點(diǎn),布局就會(huì)游刃有余。
通過(guò)添加 .form-horizontal 類,表單就可以橫向排布,此時(shí)的 .form-group 類就相當(dāng)于 .row 類,兩者的行為是一樣的,所以此時(shí)無(wú)需再添加 .row 類。
<form class="form-horizontal"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">Email</label> <div class="col-sm-10"> <input type="email" class="form-control" id="inputEmail3" placeholder="Email"> </div> </div> ... </form>
注意,在 Bootstrap 4 中, .row 類不能省略,需要寫成這樣 .form-group row 才行。其實(shí)也沒有什么區(qū)別,都是為了形成 .row > .col-* > .row > .col-* 這種結(jié)構(gòu)。
<form> <div class="form-group row"> <label for="inputEmail3" class="col-sm-2 col-form-label">Email</label> <div class="col-sm-10"> <input type="email" class="form-control" id="inputEmail3" placeholder="Email"> </div> </div> ... </form>
以下是 Bootstrap 3 橫向表單布局的例子:
See the Pen Bootstrap-demo by Zongbin (@nzbin) on CodePen.
上面的例子比官網(wǎng)多了一層?xùn)鸥瘢挥性诖笃林胁拍芸吹叫Ч@種柵格內(nèi)的表單嵌套在不熟悉 Bootstrap 的情況下很容易寫亂,但只要記住了上面提到的規(guī)則,就可以輕而易舉的寫出來(lái)。
靜態(tài)表單排列
很多人在看到上面的結(jié)構(gòu)時(shí),幾乎二話不說(shuō),就寫出 ul>li 這樣的布局,而且添加諸如 .list .item 這些無(wú)意義的類。依然是開篇提到的,我們必須始終堅(jiān)持一個(gè)原則,盡可能不要隨意添加樣式,而是探索框架本身具有的類,幾乎都可以找到解決方法。
仔細(xì)想想,上面的例子中的布局方式無(wú)非就是柵格內(nèi)的行內(nèi)表單。所以實(shí)現(xiàn)方法非常簡(jiǎn)單,完全不用自己編寫樣式。
以下是實(shí)時(shí)演示,建議在大屏查看效果:
See the Pen Bootstrap-demo by Zongbin (@nzbin) on CodePen.
表格結(jié)構(gòu)
關(guān)于表格可以說(shuō)的并不多,只是建議全部采用響應(yīng)式表格結(jié)構(gòu),也就是添加 .table-responsive 元素。因?yàn)樵趯?shí)際工作中,表格的列數(shù)一般比較多,響應(yīng)式表格應(yīng)該是更通用的方案。
<div class="table-responsive"> <table class="table"> ... </table> </div>
先排列,再排行
這條規(guī)則只是建議,因?yàn)?HTML 的塊級(jí)元素默認(rèn)是占一行,所以先排列可以減少 HTML 的結(jié)構(gòu),使結(jié)構(gòu)更簡(jiǎn)潔。另一方面,對(duì)于高度不同的元素,哪怕是很小的差距,都會(huì)出現(xiàn)布局的錯(cuò)位,見下面的 CodePen:
See the Pen Bootstrap-demo by Zongbin (@nzbin) on CodePen.
為了解決這個(gè)問題,必須在每一行都添加 .row 。不過(guò)在某些時(shí)候,我們也不得不這樣寫。
<div class="row"> <div class="col-xs-6"> ... </div> <div class="col-xs-6"> ... </div> </div> <div class="row"> <div class="col-xs-6"> ... </div> <div class="col-xs-6"> ... </div> </div> ...
如果是先排列,就不用擔(dān)心上面的問題,這種排列方式有點(diǎn)像瀑布流。
<div class="row"> <div class="col-xs-6"> ... ... </div> <div class="col-xs-6"> ... ... </div> </div>
這條建議需要根據(jù)實(shí)際的需求調(diào)整,需要和設(shè)計(jì)師以及產(chǎn)品做好溝通,不然肯定面臨返工的危險(xiǎn)。只能說(shuō)從結(jié)構(gòu)上而言,先排列會(huì)好一些。假如使用 Flex 布局的話,就可以很好地解決這個(gè)問題了。
總結(jié)
先說(shuō)點(diǎn)題外話,我一直覺得優(yōu)秀的網(wǎng)頁(yè)作品不是或者不全是設(shè)計(jì)師決定的,甚至不應(yīng)該由設(shè)計(jì)師決定,因?yàn)閲?guó)內(nèi)的設(shè)計(jì)師真正懂前端的還是少數(shù),而且設(shè)計(jì)風(fēng)格難以緊跟潮流。設(shè)計(jì)師和產(chǎn)品經(jīng)常將交互掛在嘴邊,但是他們提出的很多交互形式在我們前端人員看來(lái)都是網(wǎng)頁(yè)必備的基本要素,并不是一個(gè)亮點(diǎn)。反觀國(guó)外,設(shè)計(jì)師懂前端甚至很精通,前端開發(fā)者也是設(shè)計(jì)師或者交互設(shè)計(jì)師,每個(gè)人都是復(fù)合型人才,這是值得我們學(xué)習(xí)的方面。
言歸正傳,本文主要介紹了在使用 Bootstrap 時(shí)如何搭建更合理的結(jié)構(gòu),然而在實(shí)際工作中,不管我們用不用框架,都應(yīng)該盡可能的精簡(jiǎn)并規(guī)范化 HTML 結(jié)構(gòu),這是前端開發(fā)人員應(yīng)該養(yǎng)成的良好習(xí)慣。另外說(shuō)明一點(diǎn),因?yàn)榭蚣苁呛芏鄦栴}的抽象,所以在通用性的前提下,不可避免的會(huì)有一些冗余的 HTML 結(jié)構(gòu)。
我在開篇就強(qiáng)調(diào)盡量不要編寫冗余的樣式,但是如果真的不能滿足布局要求時(shí),我們首先應(yīng)該使用 helper 解決,Bootstrap 3 的 helper 并不豐富,而 Bootstrap 4 則添加了大量的 helper 輔助類。我在之前也寫了一篇關(guān)于 helper 的文章《如何編寫通用的 Helper Class》,感興趣的話可以看一看。