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

 更新时间:2016年07月06日 11:19:58   投稿:mrr  
这篇文章主要介绍了Bootstrap选项卡与Masonry插件的完美结合的相关资料,需要的朋友可以参考下

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

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

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

Bootstrap的Tabs

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

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

为什么是Maronry?

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

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

 

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

这就是Masonry解决问题的时候了。加一些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选项卡的网页上,上面的代码就像施了魔法。然而,在这种情况下,你很快就会发现一种有趣的行为出现。

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

 

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

 

查看源码,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中Number.isNaN 和 isNaN 的区别详解

    JavaScript中Number.isNaN 和 isNaN 的区别详解

    本文和大家分享一个前几天写代码踩的坑,笔者在业务逻辑中需要对一个值进行NaN的判断,由于笔者的不严谨,使用了isNaN,从而引起Bug,也正是因为这个,笔者才知道了isNaN和Number.isNaN的区别,所以本文就和大家聊聊它们的区别
    2023-09-09
  • 原生javaScript实现图片延时加载的方法

    原生javaScript实现图片延时加载的方法

    这篇文章主要介绍了原生javaScript实现图片延时加载的方法,无需通过载入jQuery脚本即可实现图片的延时加载效果,是非常实用的技巧,需要的朋友可以参考下
    2014-12-12
  • JS无限级导航菜单实现方法

    JS无限级导航菜单实现方法

    今天小编就为大家分享一篇关于JS无限级导航菜单实现方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • 别了 JavaScript中的isXX系列

    别了 JavaScript中的isXX系列

    我们很容易被漂亮的代码吸引,也不知不觉的在自己的代码库中加入这些。却没有冷静的想过它们的优劣。这不,我就收集了一系列形如 是否为……? 的判断的boolean函数
    2012-08-08
  • 你需要了解的ES6语法大总结

    你需要了解的ES6语法大总结

    ECMAScript是浏览器脚本语言的规范,而我们熟知的js语言,如JavaScript则是规范的具体实现,下面这篇文章主要给大家介绍了关于ES6语法总结的相关资料,需要的朋友可以参考下
    2022-05-05
  • 深入理解JavaScript中实例对象和new命令

    深入理解JavaScript中实例对象和new命令

    典型的面向对象编程语言(比如C++和 Java),都有“类”(class)这个概念。所谓“类”就是对象的模板,对象就是“类”的实例,下面这篇文章主要给大家介绍了关于JavaScript中实例对象和new命令的相关资料,需要的朋友可以参考下
    2022-12-12
  • 纯js实现无缝滚动功能代码实例

    纯js实现无缝滚动功能代码实例

    这篇文章主要介绍了纯js实现无缝滚动功能代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • uniapp实现全局变量的几种方式总结

    uniapp实现全局变量的几种方式总结

    这里说全局变量,着重指的是能够全局动态响应的情况,下面这篇文章主要给大家介绍了关于uniapp实现全局变量的几种方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • js 优化次数过多的循环 考虑到性能问题

    js 优化次数过多的循环 考虑到性能问题

    IE没有我们想象中笨,它知道总的循环次数还是一千万次。因此,得把这一百个十万次循环分开执行。虽然Javascript是单线程的,但也可以通过setTimeout或setInterval模拟多线程。
    2011-03-03
  • 跟我学习javascript的this关键字

    跟我学习javascript的this关键字

    跟我学习javascript的this关键字,this是动态绑定,或称为运行期绑定的,这就导致 JavaScript中的this关键字有能力具备多重含义,带来灵活性的同时,也为初学者带来不少困惑
    2015-11-11

最新评论