Bootstrap選項(xiàng)卡與Masonry插件的完美結(jié)合
Bootstrap 是最流行的前端框架之一。在你的項(xiàng)目中使用Bootstrap,你就可以很快的實(shí)現(xiàn)響應(yīng)式的網(wǎng)頁(yè)。
如果你嘗試將Masonry和Bootstrap提供的眾多JavaScript組件之一的 選項(xiàng)卡組件 一起使用,你將會(huì)發(fā)現(xiàn)許多討厭的行為。
我遇到過(guò),而本文主要關(guān)注這個(gè)問(wèn)題是什么和你要如何來(lái)解決這個(gè)問(wèn)題。
Bootstrap的Tabs
Bootstrap的選項(xiàng)卡組件包括兩個(gè)關(guān)鍵點(diǎn):選項(xiàng)卡導(dǎo)航元素和一些內(nèi)容面板。在頁(yè)面加載時(shí),第一個(gè)面板應(yīng)用了 .active 類。使這個(gè)面板默認(rèn)是可見(jiàn)的。這個(gè)類是通過(guò)使用JavaScript來(lái)切換面板的可見(jiàn)性,通過(guò)選項(xiàng)卡導(dǎo)航觸發(fā)的事件:如果這個(gè)面板現(xiàn)在擁有 .active 類那它是可見(jiàn)的,否則這個(gè)面板就是隱藏的。
如果你有一些網(wǎng)頁(yè)內(nèi)容最好是在單獨(dú)的塊中而不是擠在一個(gè)地方,那這種選項(xiàng)卡組件可能派上用場(chǎng)。
為什么是Maronry?
在一些情況下,在每個(gè)面板內(nèi)的內(nèi)容是適合被顯示在響應(yīng)式的網(wǎng)格布局內(nèi)的。例如,一系列的商品,服務(wù)和文件夾項(xiàng)目都是可以被顯示在網(wǎng)格格式內(nèi)的內(nèi)容類型。
然而,如果網(wǎng)格的格子不是相同的高度,那像如你所看到的下面的情況將會(huì)發(fā)生。
兩行之間被一些大的間距撐開(kāi),使布局看上去好難看。
這就是Masonry解決問(wèn)題的時(shí)候了。加一些Masonry功能到這個(gè)混亂的布局中,然后你的布局會(huì)動(dòng)態(tài)的適應(yīng)屏幕的實(shí)際面積,消除所有損壞布局的空白間距。
設(shè)置DEMO頁(yè)面
制作一個(gè)示例頁(yè)面用來(lái)展示如何整合Bootstrap的標(biāo)簽頁(yè)和Masonry并不像期望的那么簡(jiǎn)單。
本文的演示案例 是基于在Bootstrap網(wǎng)站上可用的起始模板 制作的
每個(gè)在選項(xiàng)卡面板中的網(wǎng)格項(xiàng)目都是用 Bootstrap的網(wǎng)格系統(tǒng) 和 縮略圖組件 建立的。這里是一個(gè)代碼片段來(lái)解釋它的結(jié)構(gòu):
<div class="col-sm-6 col-md-4"> <div class="thumbnail"> <img src="http://lorempixel.com/200/200/abstract" alt=""> <div class="caption"> <h3>Thumbnail label</h3> <p>...</p> <p> <a href="#" class="btn btn-primary" role="button">Button</a> <a href="#" class="btn btn-default" role="button">Button</a> </p> </div> </div> </div> <!-- Repeat two more times ... -->
上面的代碼創(chuàng)建了一個(gè)在大型屏幕上為三列,在小型屏幕上為兩列的網(wǎng)格。如果你需要復(fù)習(xí)一下Bootstrap的網(wǎng)格系統(tǒng),Syed Fazle Rahman寫的理解Bootstrap的網(wǎng)格系統(tǒng)是一篇很好的 文章 。
示例頁(yè)面中的選項(xiàng)卡組件有如下的HTML結(jié)構(gòu):
<div role="tabpanel"> <!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"> <a href="#panel-1" aria-controls="panel-1" role="tab" data-toggle="tab">Panel 1</a> </li> <li role="presentation"> <a href="#panel-2" aria-controls="panel-2" role="tab" data-toggle="tab">Panel 2</a> </li> <li role="presentation"> <a href="#panel-3" aria-controls="panel-3" role="tab" data-toggle="tab">Panel 3</a> </li> <li role="presentation"> <a href="#panel-4" aria-controls="panel-4" role="tab" data-toggle="tab">Panel 4</a> </li> </ul> <!-- Tab panels --> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="panel-1"> <div class="row masonry-container"> <div class="col-md-4 col-sm-6 item"> <!-- Thumbnail goes here --> </div> <div class="col-md-4 col-sm-6 item"> <!-- Thumbnail goes here --> </div> <div class="col-md-4 col-sm-6 item"> <!-- Thumbnail goes here --> </div> ... </div><!--End masonry-container --> </div><!--End panel-1 --> <div role="tabpanel" class="tab-pane" id="panel-2"> <!-- Same as what goes inside panel-1 --> </div><!--End panel-2 --> ... </div><!--End tab-content --> </div><!--End tabpanel -->
這里有一些關(guān)于上面代碼片段的注意事項(xiàng):
HTML注釋指出了選項(xiàng)卡的關(guān)鍵部件: Nav tabs 標(biāo)志選項(xiàng)卡的導(dǎo)航部分, Nav panels 標(biāo)志著內(nèi)容面板。
選項(xiàng)卡的鏈接通過(guò)它們 href 屬性的值連接到相應(yīng)的 id 屬性的值相同的內(nèi)容面板。例如,有著 href="#panel-1" 的鏈接打開(kāi)有著 id=panel-1 的內(nèi)容面板。
在導(dǎo)航部分的每個(gè)錨標(biāo)簽都包含 data-toggle="tab" .這個(gè)標(biāo)記使選項(xiàng)卡組件工作而無(wú)需寫任何額外的JavaScript.
Masonry的目標(biāo)元素需要有 .masonry-container 類,這個(gè)類適用于包含所有網(wǎng)格項(xiàng)目的包裝器 div 元素,還需要應(yīng)用于每單個(gè)網(wǎng)格項(xiàng)目的 .item 類。
要看到Masonry庫(kù)的全部威力,一定要確保網(wǎng)格項(xiàng)目有不同的高度。例如,刪除一個(gè)項(xiàng)目的圖片,縮短另一個(gè)項(xiàng)目的段落,等等。
完整的代碼,請(qǐng)?jiān)?a target="_blank" >CodePen中查看示例的代碼 。
添加Masonry庫(kù)
你可以在 Masonry官網(wǎng) 上通點(diǎn)擊”Download“ 按鈕下載 masonry.pkgd.min.js 。
為了避免布局問(wèn)題,庫(kù)的作者推薦將Masonry與imagesLoaded 插件 一起使用。
Masonry不需要 jQuery 。但是因?yàn)锽ootstrap的JavaScript組件已經(jīng)在使用jQuery,以jQuery的方式初始化Masonry我將會(huì)使我自己的生活更加美好。
這是我們用jQuery和imagesLoaded初始化Masonry需要的代碼段。
var $container = $('.masonry-container'); $container.imagesLoaded( function () { $container.masonry({ columnWidth: '.item', itemSelector: '.item' }); });
上面的代碼將包裹所有網(wǎng)格項(xiàng)目的 div 存儲(chǔ)在一個(gè)叫 $container 的變量中。
接下來(lái),Masonry在 $container 上用兩個(gè)推薦選項(xiàng)進(jìn)行初始化。 columnWidth 選項(xiàng)表明一個(gè)水平網(wǎng)格的一列的寬度。在這里是通過(guò)用單個(gè)網(wǎng)格項(xiàng)目的類名來(lái)設(shè)置單個(gè)網(wǎng)格項(xiàng)目的寬度的。 itemSelector 選項(xiàng)表明哪個(gè)子元素被用作項(xiàng)目元素。在這里,也設(shè)定為單個(gè)網(wǎng)格項(xiàng)目。
現(xiàn)在是時(shí)候來(lái)測(cè)試代碼了。
哎呀!隱藏的面板怎么了?
在一個(gè)不使用Bootstrap選項(xiàng)卡的網(wǎng)頁(yè)上,上面的代碼就像施了魔法。然而,在這種情況下,你很快就會(huì)發(fā)現(xiàn)一種有趣的行為出現(xiàn)。
首先,它看起來(lái)不錯(cuò),因?yàn)槟J(rèn)顯示的選項(xiàng)卡面板內(nèi)的網(wǎng)格是顯示正確的:
但是,如果你點(diǎn)擊選項(xiàng)卡導(dǎo)航鏈接顯示隱藏的面板的內(nèi)容,就會(huì)發(fā)生下面的情況:
查看源碼,Masonry已經(jīng)如預(yù)期那樣觸發(fā)了,但是每個(gè)項(xiàng)目的位置沒(méi)有被正確的計(jì)算:網(wǎng)格項(xiàng)目都像一副紙牌一樣堆在一起。
這還不是全部。調(diào)整瀏覽器窗口的大小會(huì)使這些網(wǎng)格項(xiàng)目正確定位自己。
讓我們來(lái)解決這個(gè)布局的錯(cuò)誤
因?yàn)檫@個(gè)出乎意料的布局錯(cuò)誤在點(diǎn)擊選項(xiàng)卡的導(dǎo)航鏈接之后變得更明顯,那么讓我們更密切的觀察Bootstrap選項(xiàng)卡觸發(fā)的事件。
事件列表 非常的短。如下。
show.bs.tab 觸發(fā)標(biāo)簽頁(yè)顯示,但是是在新的標(biāo)簽頁(yè)顯示之前
shown.bs.tab 觸發(fā)標(biāo)簽頁(yè)顯示,在標(biāo)簽頁(yè)顯示之后
hide.bs.tab 在新的標(biāo)簽頁(yè)將顯示的時(shí)候觸發(fā)(因此前一個(gè)顯示的標(biāo)簽頁(yè)將被隱藏)
hidden.bs.tab 在一個(gè)新的標(biāo)簽頁(yè)顯示之后觸發(fā)(因此前一個(gè)顯示的標(biāo)簽頁(yè)是隱藏的)
因?yàn)榫W(wǎng)格布局弄亂是在標(biāo)簽頁(yè)已經(jīng)被顯示之后,所以我們?nèi)フ?shown.bs.tab 事件。我們將這里的代碼放置到我們?cè)却a的下面:
$('a[data-toggle=tab]').each(function () { var $this = $(this); $this.on('shown.bs.tab', function () { $container.imagesLoaded( function () { $container.masonry({ columnWidth: '.item', itemSelector: '.item' }); }); }); });
上面的代碼中發(fā)生了什么:
jQuery .each() 函數(shù)循環(huán)遍歷每個(gè)選項(xiàng)卡導(dǎo)航鏈接,監(jiān)聽(tīng)shown.bs.tab事件。在這個(gè)事件觸發(fā)時(shí),對(duì)應(yīng)的面板變成可見(jiàn)的,同時(shí)Masonry在所有的圖片完成加載后重新初始化。
讓我們來(lái)測(cè)試代碼
如果你一直跟著文章操作,直接在您的瀏覽器中啟動(dòng)您的示例頁(yè)面,或者試試下面的CodePen示例來(lái)看看結(jié)果。
你可能也想看一下 完整的示例頁(yè)面 來(lái)測(cè)試響應(yīng)式布局效果。
點(diǎn)擊選項(xiàng)卡導(dǎo)航鏈接,注意這個(gè)時(shí)候網(wǎng)格項(xiàng)目如何在每個(gè)面板中適合均勻。改變?yōu)g覽器的大小會(huì)導(dǎo)致網(wǎng)格項(xiàng)目正確的重新定位自己的位置,并有一個(gè)漂亮的動(dòng)畫效果。
就是這樣,任務(wù)完成!
結(jié)論
在這篇文章中我已經(jīng)展示了如何整合Bootstrap的標(biāo)簽頁(yè)和Masonry JavaScript庫(kù)。
這兩個(gè)腳本都容易使用并且非常強(qiáng)大。然而,將它們兩個(gè)放到一起你將會(huì)面臨一些影響隱藏的選項(xiàng)卡的布局漏洞。如上面所示,訣竅就是在每個(gè)面板變成可見(jiàn)之后重新初始化Masonry庫(kù)。
- 全面解析Bootstrap中tab(選項(xiàng)卡)的使用方法
- BootStrap tab選項(xiàng)卡使用小結(jié)
- bootstrap選項(xiàng)卡使用方法解析
- bootstrap實(shí)現(xiàn)tab選項(xiàng)卡切換
- 簡(jiǎn)單實(shí)現(xiàn)bootstrap選項(xiàng)卡效果
- bootstrap導(dǎo)航、選項(xiàng)卡實(shí)現(xiàn)代碼
- bootstrap選項(xiàng)卡擴(kuò)展功能詳解
- Bootstrap選項(xiàng)卡學(xué)習(xí)筆記分享
- 淺談bootstrap源碼分析之tab(選項(xiàng)卡)
- BootstrapVue選項(xiàng)卡標(biāo)題增加關(guān)閉按鈕的方法
相關(guān)文章
一個(gè)對(duì)于Array的簡(jiǎn)單擴(kuò)展
一個(gè)對(duì)于Array的簡(jiǎn)單擴(kuò)展...2006-10-10js中回調(diào)函數(shù)的學(xué)習(xí)筆記
這篇文章主要介紹了js中回調(diào)函數(shù)的相關(guān)知識(shí),需要的朋友可以參考下2014-07-07詳解axios中封裝使用、攔截特定請(qǐng)求、判斷所有請(qǐng)求加載完畢)
這篇文章主要介紹了axios中封裝使用、攔截特定請(qǐng)求、判斷所有請(qǐng)求加載完畢的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04JS實(shí)現(xiàn)仿百度輸入框自動(dòng)匹配功能的示例代碼
本篇文章主要是對(duì)JS實(shí)現(xiàn)仿百度輸入框自動(dòng)匹配功能的示例代碼進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-02-02直接在JS里創(chuàng)建JSON數(shù)據(jù)然后遍歷使用
本節(jié)為大家講解下直接在JS里創(chuàng)建JSON數(shù)據(jù),然后遍歷使用,需要的朋友可以參考下2014-07-07javaScript把其它類型轉(zhuǎn)換為Number類型
在本篇文章里小編給大家整理的是關(guān)于javaScript把其它類型轉(zhuǎn)換為Number類型的相關(guān)文章,有需要的朋友們學(xué)習(xí)下。2019-10-10如何通過(guò)javaScript去除字符串兩端的空白字符
這篇文章主要介紹了如何通過(guò)javaScripte去除字符串兩端的空白字符,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02