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 相关文章推荐
JavaScript toFixed() 方法
Apr 15 Javascript
基于jQuery的烟花效果(运动相关)点击屏幕出烟花
Jun 14 Javascript
JavaScript中变量提升 Hoisting
Jul 03 Javascript
JS实现的鼠标跟随代码(卡通手型点击效果)
Oct 26 Javascript
node.js中的事件处理机制详解
Nov 26 Javascript
利用HTML5+Socket.io实现摇一摇控制PC端歌曲切换
Jan 13 Javascript
IScroll那些事_当内容不足时下拉刷新的解决方法
Jul 18 Javascript
js微信分享实现代码
Oct 11 Javascript
jquery ztree实现右键收藏功能
Nov 20 jQuery
vue 开发一个按钮组件的示例代码
Mar 27 Javascript
Vue中util的工具函数实例详解
Jul 08 Javascript
node.js通过Sequelize 连接MySQL的方法
Dec 28 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 shell命令合并图片的代码
2011/06/23 PHP
PHP 命令行工具 shell_exec, exec, passthru, system详细使用介绍
2011/09/11 PHP
向fckeditor编辑器插入指定代码的方法
2007/05/25 Javascript
js+css在交互上的应用
2010/07/18 Javascript
jQuery常见开发技巧详细整理
2013/01/02 Javascript
window.navigate 与 window.location.href 的使用区别介绍
2013/09/21 Javascript
js实现字符串的16进制编码不加密
2014/04/25 Javascript
JS表的模拟方法
2015/02/05 Javascript
jquery动感漂浮导航菜单代码分享
2020/04/15 Javascript
js实现不提交表单获取单选按钮值的方法
2015/08/21 Javascript
详解JavaScript UTC时间转换方法
2016/01/07 Javascript
AngularJS中的API(接口)简单实现
2016/07/28 Javascript
jQuery实现的placeholder效果完整实例
2016/08/02 Javascript
深入理解requestAnimationFrame的动画循环
2016/09/20 Javascript
微信小程序入门教程
2016/11/18 Javascript
微信小程序 数组中的push与concat的区别
2017/01/05 Javascript
基于AngularJS的拖拽文件上传的实例代码
2017/07/15 Javascript
jQuery选取所有复选框被选中的值并用Ajax异步提交数据的实例
2017/08/04 jQuery
JS脚本实现网页自动秒杀点击
2018/01/11 Javascript
vue中$refs的用法及作用详解
2018/04/24 Javascript
解决vue+webpack项目接口跨域出现的问题
2020/08/10 Javascript
深入讲解Python编程中的字符串
2015/10/14 Python
Python设计实现的计算器功能完整实例
2017/08/18 Python
Python使用graphviz画流程图过程解析
2020/03/31 Python
html5是什么_动力节点Java学院整理
2017/07/07 HTML / CSS
Linux不知道文件后缀名怎么判断文件类型
2012/04/26 面试题
一名毕业生的自我鉴定
2013/12/04 职场文书
煤矿班组长竞聘书
2014/03/31 职场文书
新学期开学演讲稿
2014/05/24 职场文书
预防煤气中毒方案
2014/06/16 职场文书
乡镇党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
工资证明格式模板
2015/06/12 职场文书
工作简报怎么写
2015/07/21 职场文书
毕业生的自我鉴定表范文
2019/05/16 职场文书
致男子1500米运动员的广播稿
2019/11/08 职场文书
spring注解 @PropertySource配置数据源全流程
2022/03/25 Java/Android