Bootstrap选项卡与Masonry插件的完美结合


Posted in Javascript onJuly 06, 2016

Bootstrap 是最流行的前端框架之一。在你的项目中使用Bootstrap,你就可以很快的实现响应式的网页。

如果你尝试将Masonry和Bootstrap提供的众多JavaScript组件之一的 选项卡组件 一起使用,你将会发现许多讨厌的行为。

我遇到过,而本文主要关注这个问题是什么和你要如何来解决这个问题。

Bootstrap的Tabs

Bootstrap的选项卡组件包括两个关键点:选项卡导航元素和一些内容面板。在页面加载时,第一个面板应用了 .active 类。使这个面板默认是可见的。这个类是通过使用JavaScript来切换面板的可见性,通过选项卡导航触发的事件:如果这个面板现在拥有 .active 类那它是可见的,否则这个面板就是隐藏的。

如果你有一些网页内容最好是在单独的块中而不是挤在一个地方,那这种选项卡组件可能派上用场。

为什么是Maronry?

在一些情况下,在每个面板内的内容是适合被显示在响应式的网格布局内的。例如,一系列的商品,服务和文件夹项目都是可以被显示在网格格式内的内容类型。

然而,如果网格的格子不是相同的高度,那像如你所看到的下面的情况将会发生。

Bootstrap选项卡与Masonry插件的完美结合 

两行之间被一些大的间距撑开,使布局看上去好难看。

这就是Masonry解决问题的时候了。加一些Masonry功能到这个混乱的布局中,然后你的布局会动态的适应屏幕的实际面积,消除所有损坏布局的空白间距。

Bootstrap选项卡与Masonry插件的完美结合 

设置DEMO页面

制作一个示例页面用来展示如何整合Bootstrap的标签页和Masonry并不像期望的那么简单。

本文的演示案例 是基于在Bootstrap网站上可用的起始模板 制作的

每个在选项卡面板中的网格项目都是用 Bootstrap的网格系统 和 缩略图组件 建立的。这里是一个代码片段来解释它的结构:

<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 ... -->

上面的代码创建了一个在大型屏幕上为三列,在小型屏幕上为两列的网格。如果你需要复习一下Bootstrap的网格系统,Syed Fazle Rahman写的理解Bootstrap的网格系统是一篇很好的 文章 。

示例页面中的选项卡组件有如下的HTML结构:

<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 -->

这里有一些关于上面代码片段的注意事项:

HTML注释指出了选项卡的关键部件: Nav tabs 标志选项卡的导航部分, Nav panels 标志着内容面板。
选项卡的链接通过它们 href 属性的值连接到相应的 id 属性的值相同的内容面板。例如,有着 href="#panel-1" 的链接打开有着 id=panel-1 的内容面板。

在导航部分的每个锚标签都包含 data-toggle="tab" .这个标记使选项卡组件工作而无需写任何额外的JavaScript.
Masonry的目标元素需要有 .masonry-container 类,这个类适用于包含所有网格项目的包装器 div 元素,还需要应用于每单个网格项目的 .item 类。

要看到Masonry库的全部威力,一定要确保网格项目有不同的高度。例如,删除一个项目的图片,缩短另一个项目的段落,等等。

完整的代码,请在CodePen中查看示例的代码 。

添加Masonry库

你可以在 Masonry官网 上通点击”Download“ 按钮下载 masonry.pkgd.min.js 。

为了避免布局问题,库的作者推荐将Masonry与imagesLoaded 插件 一起使用。

Masonry不需要 jQuery 。但是因为Bootstrap的JavaScript组件已经在使用jQuery,以jQuery的方式初始化Masonry我将会使我自己的生活更加美好。

这是我们用jQuery和imagesLoaded初始化Masonry需要的代码段。

var $container = $('.masonry-container');
$container.imagesLoaded( function () {
$container.masonry({
columnWidth: '.item',
itemSelector: '.item'
}); 
});

上面的代码将包裹所有网格项目的 div 存储在一个叫 $container 的变量中。

接下来,Masonry在 $container 上用两个推荐选项进行初始化。 columnWidth 选项表明一个水平网格的一列的宽度。在这里是通过用单个网格项目的类名来设置单个网格项目的宽度的。 itemSelector 选项表明哪个子元素被用作项目元素。在这里,也设定为单个网格项目。

现在是时候来测试代码了。

哎呀!隐藏的面板怎么了?

在一个不使用Bootstrap选项卡的网页上,上面的代码就像施了魔法。然而,在这种情况下,你很快就会发现一种有趣的行为出现。

首先,它看起来不错,因为默认显示的选项卡面板内的网格是显示正确的:

Bootstrap选项卡与Masonry插件的完美结合 

但是,如果你点击选项卡导航链接显示隐藏的面板的内容,就会发生下面的情况:

Bootstrap选项卡与Masonry插件的完美结合 

查看源码,Masonry已经如预期那样触发了,但是每个项目的位置没有被正确的计算:网格项目都像一副纸牌一样堆在一起。

这还不是全部。调整浏览器窗口的大小会使这些网格项目正确定位自己。

让我们来解决这个布局的错误

因为这个出乎意料的布局错误在点击选项卡的导航链接之后变得更明显,那么让我们更密切的观察Bootstrap选项卡触发的事件。

事件列表 非常的短。如下。

show.bs.tab 触发标签页显示,但是是在新的标签页显示之前
shown.bs.tab 触发标签页显示,在标签页显示之后
hide.bs.tab 在新的标签页将显示的时候触发(因此前一个显示的标签页将被隐藏)
hidden.bs.tab 在一个新的标签页显示之后触发(因此前一个显示的标签页是隐藏的)

因为网格布局弄乱是在标签页已经被显示之后,所以我们去找 shown.bs.tab 事件。我们将这里的代码放置到我们原先代码的下面:

$('a[data-toggle=tab]').each(function () {
var $this = $(this);
$this.on('shown.bs.tab', function () {
$container.imagesLoaded( function () {
$container.masonry({
columnWidth: '.item',
itemSelector: '.item'
}); 
}); 
});
});

上面的代码中发生了什么:

jQuery .each() 函数循环遍历每个选项卡导航链接,监听shown.bs.tab事件。在这个事件触发时,对应的面板变成可见的,同时Masonry在所有的图片完成加载后重新初始化。

让我们来测试代码

如果你一直跟着文章操作,直接在您的浏览器中启动您的示例页面,或者试试下面的CodePen示例来看看结果。

你可能也想看一下 完整的示例页面 来测试响应式布局效果。

点击选项卡导航链接,注意这个时候网格项目如何在每个面板中适合均匀。改变浏览器的大小会导致网格项目正确的重新定位自己的位置,并有一个漂亮的动画效果。

就是这样,任务完成!

结论

在这篇文章中我已经展示了如何整合Bootstrap的标签页和Masonry JavaScript库。

这两个脚本都容易使用并且非常强大。然而,将它们两个放到一起你将会面临一些影响隐藏的选项卡的布局漏洞。如上面所示,诀窍就是在每个面板变成可见之后重新初始化Masonry库。

Javascript 相关文章推荐
打开超链需要“确认”对话框的方法
Mar 08 Javascript
Mootools 1.2教程 定时器和哈希简介
Sep 15 Javascript
JavaScript使用IEEE 标准进行二进制浮点运算产生莫名错误的解决方法
May 28 Javascript
字段太多jquey快速清空表单内容方法
Aug 21 Javascript
详解JavaScript中双等号引起的隐性类型转换
May 30 Javascript
vue 组件使用中的一些细节点
Apr 25 Javascript
BootStrap模态框闪退问题实例代码详解
Dec 10 Javascript
vuex 中插件的编写案例解析
Jun 10 Javascript
JS前端知识点offset,scroll,client,冒泡,事件对象的应用整理总结
Jun 27 Javascript
js回调函数仿360开机
Dec 26 Javascript
JS this关键字在ajax中使用出现问题解决方案
Jul 17 Javascript
JavaScript中document.activeELement焦点元素介绍
Nov 27 Javascript
针对BootStrap中tabs控件的美化和完善(推荐)
Jul 06 #Javascript
jQuery插件dataTables添加序号列的方法
Jul 06 #Javascript
Spring MVC中Ajax实现二级联动的简单实例
Jul 06 #Javascript
js中window.open的参数及注意注意事项
Jul 06 #Javascript
快速解决js动态改变dom元素属性后页面及时渲染的问题
Jul 06 #Javascript
jQuery 3.0十大新特性
Jul 06 #Javascript
Javascript 基础---Ajax入门必看
Jul 06 #Javascript
You might like
PHP各种异常和错误的拦截方法及发生致命错误时进行报警
2016/01/19 PHP
PHP实现适用于文件内容操作的分页类
2016/06/15 PHP
php判断文件上传图片格式的实例详解
2017/09/30 PHP
Google Suggest ;-) 基于js的动态下拉菜单
2006/10/11 Javascript
JS实现的数组全排列输出算法
2015/03/19 Javascript
jQuery实现商品活动倒计时
2015/10/16 Javascript
详解JavaScript中常用的函数类型
2015/11/18 Javascript
jQuery增加与删除table列的方法
2016/03/01 Javascript
Select下拉框模糊查询功能实现代码
2016/07/22 Javascript
Bootstrap源码解读媒体对象、列表组和面板(10)
2016/12/26 Javascript
Javascript 实现计算器时间功能详解及实例(二)
2017/01/08 Javascript
用move.js库实现百叶窗特效
2017/02/08 Javascript
requirejs按需加载angularjs文件实例
2017/06/08 Javascript
VUE2实现事件驱动弹窗示例
2017/10/21 Javascript
在Vue中使用echarts的方法
2018/02/05 Javascript
小程序根据手机机型设置自定义底部导航距离
2019/06/04 Javascript
[02:40]2014DOTA2 国际邀请赛中国区预选赛 四大豪门抵达华西村
2014/05/23 DOTA
zbar解码二维码和条形码示例
2014/02/07 Python
python实现删除文件与目录的方法
2014/11/10 Python
python 根据正则表达式提取指定的内容实例详解
2016/12/04 Python
python中装饰器级连的使用方法示例
2017/09/29 Python
Django框架创建项目的方法入门教程
2019/11/04 Python
pycharm工具连接mysql数据库失败问题
2020/04/01 Python
Python爬取阿拉丁统计信息过程图解
2020/05/12 Python
python3.5的包存放的具体路径
2020/08/16 Python
PyCharm 2020.1版安装破解注册码永久激活(激活到2089年)
2020/09/24 Python
matplotlib之pyplot模块之标题(title()和suptitle())
2021/02/22 Python
汉米尔顿手表官网:Hamilton
2020/09/13 全球购物
医学专业个人求职自荐信格式
2013/09/23 职场文书
自我评价是什么
2014/01/04 职场文书
《四季》教学反思
2014/04/08 职场文书
党员专题组织生活会发言材料
2014/10/17 职场文书
2015年公共机构节能宣传周活动总结
2015/03/26 职场文书
2015年酒店工作总结范文
2015/04/07 职场文书
2015年医院科室工作总结范文
2015/05/26 职场文书
浅谈mysql增加索引不生效的几种情况
2021/06/23 MySQL