Bootstrap is one of the most popular front-end frameworks. Using Bootstrap in your project, you can quickly implement responsive web pages.
If you try to use Masonry and the tab component of one of the many JavaScript components provided by Bootstrap, you will find a lot of annoying behavior.
I've encountered this article, and this article focuses on what this issue is and how you want to solve it.
Bootstrap's Tabs
Bootstrap's tab component includes two key points: the tab navigation element and some content panels. When the page loads, the first panel applies the .active class. Make this panel visible by default. This class switches the visibility of the panel by using JavaScript, and triggers events through tab navigation: if this panel now has the .active class, then it is visible, otherwise the panel is hidden.
If you have some web content that is better in separate blocks rather than crowded in one place, this kind of tab component may come in handy.
Why Maronry?
In some cases, the content within each panel is suitable for being displayed within a responsive grid layout. For example, a range of goods, services, and folder items are all content types that can be displayed in a grid format.
However, if the grids of the grid are not at the same height, then something like you can see below will happen.
The two lines are stretched out by some large spacing, making the layout look ugly.
This is the time for Masonry to solve the problem. Add some Masonry functions to this messy layout, and then your layout will dynamically adapt to the actual area of the screen, eliminating the blank spacing of all damaged layouts.
Setting up DEMO page
Making a sample page to show how to integrate Bootstrap's tabs and Masonry is not as simple as expected.
The demo case in this article is based on the starting template available on the Bootstrap website
Each grid project in the tab panel is built using Bootstrap's grid system and thumbnail components. Here is a code snippet to explain its structure:
<div><div><img src="http://lorempixel.com/200/200/abstract"><div><h3>Thumbnail label</h3><p>...</p><p><a href="#" role="button">Button</a> <a href="#" role="button">Button</a></p></div></div> <!-- Repeat two more times ... -->
The above code creates a grid with three columns on a large screen and two columns on a small screen. If you need to review Bootstrap's grid system, Syed Fazle Rahman's understanding of Bootstrap's grid system is a good article.
The tab components in the example page have the following HTML structure:
<div role="tabpanel"><!-- Nav tabs --><ul role="tablist"><li role="presentation"><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><div role="tabpanel" id="panel-1"><div><div><!-- Thumbnail goes here --></div><div><!-- Thumbnail goes here --></div><div><!-- Thumbnail goes here --></div><div><!-- Thumbnail goes here --></div>...</div><!--End masonry-container --></div><!--End panel-1 --><div role="tabpanel" id="panel-2"><!-- Same as what goes inside panel-1 --></div><!--End panel-2 -->...</div><!--End tab-content --></div><!--End tabpanel -->
Here are some notes about the above code snippet:
HTML comments point out the key components of the tab: Nav tabs mark the navigation section of the tab, and Nav panels mark the content panel.
The links to the tabs are connected to the content panel with the same value of the corresponding id attribute through their href attribute. For example, a link with href="#panel-1" opens a content panel with id=panel-1.
Each anchor tag in the navigation section contains data-toggle="tab". This tag allows the tab component to work without writing any additional JavaScript.
Masonry's target element needs to have the .masonry-container class, which is suitable for wrapper div elements containing all grid items, and also needs to be applied to the .item class for each single grid item.
To see the full power of the Masonry library, be sure to ensure that the grid items have different heights. For example, deleting an image of one project, shortening paragraphs of another project, etc.
For the complete code, please check the code for the example in CodePen.
Adding Masonry library
You can download masonry.pkgd.min.js by clicking the "Download" button on the official website of Masonry.
To avoid layout issues, the library's author recommends using Masonry with the imagesLoaded plugin.
Masonry does not require jQuery. But because Bootstrap's JavaScript component is already using jQuery, initializing Masonry in jQuery way I will make my own life better.
This is the code snippet we need to initialize Masonry with jQuery and imagesLoaded.
var $container = $('.masonry-container');$container.imagesLoaded( function () {$container.masonry({columnWidth: '.item',itemSelector: '.item'}); });The above code stores the div that wraps all grid items in a variable called $container.
Next, Masonry initializes it with two recommended options on $container. The columnWidth option indicates the width of a column of a horizontal grid. Here, the width of a single grid item is set by using the class name of a single grid item. The itemSelector option indicates which child element is used as the project element. Here, it is also set as a single grid item.
Now it's time to test the code.
oops! What's wrong with the hidden panel?
On a web page that does not use the Bootstrap tab, the above code is like magic. However, in this case, you will soon find an interesting behavior to appear.
First, it looks good because the grid inside the tab panel displayed by default is displayed correctly:
However, if you click on the tab navigation link to display the contents of the hidden panel, the following will happen:
Looking at the source code, Masonry has triggered as expected, but the position of each item is not calculated correctly: the grid items are piled together like a deck of cards.
That's not all. Resizing the browser window will enable these grid items to correctly position themselves.
Let's resolve this layout error
Because this unexpected layout error becomes more obvious after clicking on the navigation link of the tab, let's watch more closely the events triggered by the Bootstrap tab.
The event list is very short. as follows.
show.bs.tab triggers the tab page to display, but before the new tab page is displayed
shown.bs.tab triggers the tab page to display, after the tab page is displayed
hide.bs.tab triggers when the new tab page will be displayed (so the previous displayed tab page will be hidden)
hidden.bs.tab is fired after a new tab page is displayed (so the previous displayed tab page is hidden)
Because the grid layout is messed up after the tab page has been displayed, we go to the show.bs.tab event. We place the code here below our original code:
$('a[data-toggle=tab]').each(function () {var $this = $(this);$this.on('shown.bs.tab', function () {$container.imagesLoaded( function () {$container.masonry({columnWidth: '.item',itemSelector: '.item'}); }); }); });What's happening in the above code:
The jQuery .each() function loops through each tab navigation link and listens for the shown.bs.tab event. When this event is triggered, the corresponding panel becomes visible, and Masonry re-initializes all images after loading.
Let's test the code
If you keep following the article, start your sample page directly in your browser, or try the CodePen example below to see the results.
You might also want to take a look at the full example page to test the responsive layout effect.
Click the tab navigation link and pay attention to how the grid items fit evenly in each panel at this time. Changing the browser size will cause the grid project to correctly reposition itself and have a nice animation effect.
That's it, the task is completed!
in conclusion
In this post I have shown how to integrate Bootstrap's tabs and Masonry JavaScript libraries.
Both scripts are easy to use and very powerful. However, putting them both together you will face some layout vulnerabilities that affect hidden tabs. As shown above, the trick is to re-initialize the Masonry library after each panel becomes visible.