glidejs

How to load a Glide.js slider in a hidden element, which is later displayed


I am using https://glidejs.com/

Is there a way to handle sliders in hidden elements, that are later displayed?

Specfically in my case, a Bootstrap tab panel. The slider appears unable to calculate it's size correctly if mounted when hidden and then made visible. If you resize the browser window, the slider then resizes and looks correct.

Here's a code example

https://codepen.io/atghugh/pen/BabaNMZ

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bootstrap demo</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Glide.js/3.2.0/css/glide.core.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Glide.js/3.2.0/css/glide.theme.css">
</head>

<body style="padding:25px; width:370px">
  <!-- Nav tabs -->
  <ul class="nav nav-tabs" id="myTab" role="tablist">
    <li class="nav-item" role="presentation">
      <button class="nav-link active" id="visible-tab" data-bs-toggle="tab" data-bs-target="#visible" type="button" role="tab" aria-controls="home" aria-selected="true">Visible</button>
    </li>
    <li class="nav-item" role="presentation">
      <button class="nav-link" id="hidden-tab" data-bs-toggle="tab" data-bs-target="#hidden" type="button" role="tab" aria-controls="profile" aria-selected="false">Hidden</button>
    </li>
  </ul>

  <!-- Tab panes -->
  <div class="tab-content" style="padding:10px">
    <div class="tab-pane active" id="visible" role="tabpanel" aria-labelledby="visble-tab" tabindex="0">
      <div class="glide" id="glide-visible">
        <div data-glide-el="track" class="glide__track">
          <ul class="glide__slides" style="width:300px">
            <li class="glide__slide">
              <img src="https://picsum.photos/id/1/300/300" />
            </li>
            <li class="glide__slide">
              <img src="https://picsum.photos/id/2/300/300" />
            </li>
            <li class="glide__slide">
              <img src="https://picsum.photos/id/3/300/300" />
            </li>
          </ul>
        </div>
        <div class="glide__arrows" data-glide-el="controls">
          <button class="glide__arrow glide__arrow--left" data-glide-dir="<">&lt;</button>
          <button class="glide__arrow glide__arrow--right" data-glide-dir=">">&gt;</button>
        </div>
      </div>

    </div>
    <div class="tab-pane" id="hidden" role="tabpanel" aria-labelledby="hidden-tab" tabindex="0">

      <div class="glide" id="glide-hidden">
        <div data-glide-el="track" class="glide__track">
          <ul class="glide__slides">
            <li class="glide__slide">
              <img src="https://picsum.photos/id/4/300/300" />
            </li>
            <li class="glide__slide">
              <img src="https://picsum.photos/id/5/300/300" />
            </li>
            <li class="glide__slide">
              <img src="https://picsum.photos/id/6/300/300" />
            </li>
          </ul>
        </div>
        <div class="glide__arrows" data-glide-el="controls">
          <button class="glide__arrow glide__arrow--left" data-glide-dir="<">&lt;</button>
          <button class="glide__arrow glide__arrow--right" data-glide-dir=">">&gt;</button>
        </div>
      </div>

    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Glide.js/3.2.0/glide.js"></script>
  <script>
    new Glide('#glide-hidden', {
      type: 'carousel'
    }).mount()
    new Glide('#glide-visible', {
      type: 'carousel'
    }).mount()
  </script>
</body>

</html>

Thanks.


Solution

  • In the end I used an IntersectionObserver to mount the Slider when it becomes visible.

    let slider = document.querySelector('.glide');
    
    const observer = new IntersectionObserver((entries, _observer) => {
      entries.forEach(entry => {    
        if(entry.isIntersecting) {                                                                          
          this.slider.mount();                                                                             
        }  
      });
    });
                                              
    observer.observe(slider);