Search code examples
javascriptjqueryhtmltwitter-bootstrapowl-carousel

Owl carousel and bootstrap tab on a page


I am trying to build a page using both bootstrap and a Owl carousel, Owl carousel fit the purpose of the site rather that bootstraps version. So I got a tab structure where I want to put a carousel on each page, however all my attempts have failed. Here is my code

<div role="tabpanel">

<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
 <li role="presentation" class="active"><a href="#home" aria-controls="home" role="tab" data-toggle="tab">Home</a></li>
 <li role="presentation"><a href="#profile" aria-controls="profile" role="tab" data-toggle="tab">Profile</a></li>
 <li role="presentation"><a href="#messages" aria-controls="messages" role="tab" data-toggle="tab">Messages</a></li>
 <li role="presentation"><a href="#settings" aria-controls="settings" role="tab" data-toggle="tab">Settings</a></li>
</ul>

<!-- Tab panes -->
<div class="tab-content">
 <div role="tabpanel" class="tab-pane active" id="home">
  <div class="owl-carousel" id="owl1">
   <div> content</div>
   <div> content</div>
  </div>
 </div>
 <div role="tabpanel" class="tab-pane" id="profile">
  <div class="owl-carousel" id="owl2">
   <div> content</div>
   <div> content</div>
  </div>
 <div role="tabpanel" class="tab-pane" id="messages">
  <div class="owl-carousel" id="owl3">
   <div> content</div>
   <div> content</div>
  </div>
 </div>
<div role="tabpanel" class="tab-pane" id="settings">
  <div class="owl-carousel" id="owl4">
   <div> content</div>
   <div> content</div>
  </div>
 </div>
</div>
</div>

Here is my javascript

$(document).ready(function () {
    $('#owl1').owlCarousel({
        loop: true,
        margin: 10,
        responsiveClass: true,
        responsive: {
            0: {
               items: 1,
                nav: true
            },
            600: {
                items: 1,
                nav: false
            },
            1000: {
                items: 1,
                nav: true,
                loop: false
            }
        }
    });
    $('#owl2').owlCarousel({
        loop: true,
        margin: 10,
        responsiveclass: true,
        responsive: {
            0: {
                items: 1,
                nav: true
            },
            600: {
                items: 1,
                nav: false
            },
            1000: {
                items: 1,
                nav: true,
                loop: false
            }
        }
    });
    $('#owl3').owlCarousel({
        loop: true,
        margin: 10,
        responsiveclass: true,
        responsive: {
            0: {
                items: 1,
                nav: true
            },
            600: {
                items: 1,
                nav: false
            },
            1000: {
                items: 1,
                nav: true,
                loop: false
            }
        }
    });
    $('#owl4').owlCarousel({
        loop: true,
        margin: 10,
        responsiveclass: true,
        responsive: {
            0: {
                items: 1,
                nav: true
            },
            600: {
                items: 1,
                nav: false
            },
            1000: {
                items: 1,
                nav: true,
                loop: false
            }
        }
    });

//});

http://www.owlcarousel.owlgraphic.com/docs/api-events.html


Solution

  • First, I noticed an error in your html. You are missing a closing </div> tag for your second tab-pane. That's throwing off some of the structure of your markup.

    After researching and playing around with this, it seems that this is a known issue. It stems from the fact that Bootstraps tabs are hidden initially. When you try to initialize an OwlCarousel within a hidden element, things go badly because hidden elements have no width, so Owl does not know how much space it has to work with.

    My solution is to wait until a tab is shown to initialize the carousel, then destroy the carousel each time the tab is hidden. Here's my JavaScript:

    $(document).ready(function () {
      initialize_owl($('#owl1'));
    
      let tabs = [
        { target: '#home', owl: '#owl1' },
        { target: '#profile', owl: '#owl2' },
        { target: '#messages', owl: '#owl3' },
        { target: '#settings', owl: '#owl4' },
      ];
    
      // Setup 'bs.tab' event listeners for each tab
      tabs.forEach((tab) => {
        $(`a[href="${ tab.target }"]`)
          .on('shown.bs.tab', () => initialize_owl($(tab.owl)))
          .on('hide.bs.tab', () => destroy_owl($(tab.owl)));
      }); 
    });
    
    function initialize_owl(el) {
      el.owlCarousel({
        loop: true,
        margin: 10,
        responsiveClass: true,
        responsive: {
          0: {
            items: 1,
            nav: true
          },
          600: {
            items: 1,
            nav: false
          },
          1000: {
            items: 1,
            nav: true,
            loop: false
          }
        }
      });
    }
    
    function destroy_owl(el) {
      el.data('owlCarousel').destroy();
    }
    

    And here's a working jsFiddle.