skip to Main Content

This is my code:

$(document).ready(function() {
  $('.scrollable-area').on('wheel', function(e) {
    var scrollLeft = $(this).scrollLeft();
    var width = $(this).get(0).scrollWidth - $(this).width();
    var deltaY = e.originalEvent.deltaY;
    var deltaX = e.originalEvent.deltaX;
    var newScrollLeft = scrollLeft + deltaY + deltaX;
    if ((deltaY > 0 && newScrollLeft < width) ||
      (deltaY < 0 && newScrollLeft > 0)) {
      e.preventDefault();
    }
    if (newScrollLeft <= 0) {
      $(this).scrollLeft(0);
    } else if (newScrollLeft >= width) {
      $(this).scrollLeft(width);
    } else {
      $(this).scrollLeft(newScrollLeft);
    }
  });
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.gallery-container {
  position: relative;
  width: 100%;
  height: 90vh;
  background-color: yellow;
  overflow: hidden;
}

.scrollable-area {
  width: 100%;
  height: 100%;
  overflow-x: auto;
}

.gallery-items {
  display: flex;
  min-width: 100%;
  height: 100%;
}

.gallery-item {
  flex: 0 0 auto;
  height: 100%;
  display: flex;
}

.gallery-item img {
  max-width: 100%;
  height: auto;
  object-fit: contain;
}

.gallery-item iframe {
  background-color: blue;
  width: auto;
  width: 800px;
}
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>

<div class="gallery-container">
  <div class="scrollable-area">
    <div class="gallery-items">
      <div class="gallery-item">
        <img src="https://upload.wikimedia.org/wikipedia/commons/1/16/Appearance_of_sky_for_weather_forecast%2C_Dhaka%2C_Bangladesh.JPG">
      </div>
      <div class="gallery-item">
        <img src="https://upload.wikimedia.org/wikipedia/commons/d/da/Sky_landscape.jpg">
      </div>
      <div class="gallery-item">
        <iframe src="https://player.vimeo.com/video/584985260" frameborder="0" allow="fullscreen"></iframe>
      </div>
      <div class="gallery-item">
        <img src="https://upload.wikimedia.org/wikipedia/commons/1/16/Appearance_of_sky_for_weather_forecast%2C_Dhaka%2C_Bangladesh.JPG">
      </div>
    </div>
  </div>
</div>

If you have the cursor on the media gallery and scroll down normally, you first scroll horizontally through the gallery. That’s on purpose. However, it stops when an iframe is included. I’ve already tried to prevent the pointer events during scrolling, but it lead to some other issues like it was not possible anymore to click the play button of a video.

Also, it would be cool to find a way to always resize the iframe to that of the video and overall fit the height of the horizontal gallery. Does anyone know how this works?

2

Answers


  1. Modify your jQuery code to handle scrolling events for both images and iframes and you may also dynamically resize the iframes to fit their content and adjust the height of the horizontal gallery accordingly.

    <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
    <script>
      $(document).ready(function() {
        $('.scrollable-area').on('wheel', function(e) {
          var scrollLeft = $(this).scrollLeft();
          var width = $(this).get(0).scrollWidth - $(this).width();
          var deltaY = e.originalEvent.deltaY;
          var deltaX = e.originalEvent.deltaX;
          var newScrollLeft = scrollLeft + deltaY + deltaX;
          if ((deltaY > 0 && newScrollLeft < width) ||
            (deltaY < 0 && newScrollLeft > 0)) {
            e.preventDefault();
          }
          if (newScrollLeft <= 0) {
            $(this).scrollLeft(0);
          } else if (newScrollLeft >= width) {
            $(this).scrollLeft(width);
          } else {
            $(this).scrollLeft(newScrollLeft);
          }
        });
    
        // Resize iframes to fit their content
        function resizeIframes() {
          $('.gallery-item iframe').each(function() {
            this.height = this.contentWindow.document.body.scrollHeight + 'px';
          });
        }
    
        // Call the function on initial load and on window resize
        resizeIframes();
        $(window).resize(function() {
          resizeIframes();
        });
      });
    </script>
    
    Login or Signup to reply.
  2. You might add an overlay to your scrolling div to disable iframe pointer events and re-enable pointer events on mouse movements.

    Based on trincot’s answer "How to detect when mousemove has stopped"
    we could use a custom mousestop event.

    1. we disable iframe pointer events by appending an overlay.
    2. we’re toggling/discarding the overlay according to mouse movements:
      if mouse moves were stopped (using a setTimeout delay) we add/activate the overlay to block pointer events within the iframe content – enabling wheel scroll events
      When moving over the slider wrap – we can access iframe/slide buttons.
    3. iframe dimensions are simply set via aspect-ratio e.g. 16/9
    let galleryWrap = document.querySelector('.gallery-container');
    
    
    (function(mouseStopDelay) {
      var timeout;
      document.addEventListener('mousemove', function(e) {
        clearTimeout(timeout);
        timeout = setTimeout(function() {
          var event = new CustomEvent("mousestop", {
            detail: {
              clientX: e.clientX,
              clientY: e.clientY
            },
            bubbles: true,
            cancelable: true
          });
          e.target.dispatchEvent(event);
        }, mouseStopDelay);
      });
    }(1000));
    
    // Example use
    galleryWrap.addEventListener('mousestop', function(e) {
      galleryWrap.classList.add('inactive')
    });
    
    galleryWrap.addEventListener('mousemove', function(e) {
      galleryWrap.classList.remove('inactive')
    });
    
    galleryWrap.addEventListener('click', function(e) {
      galleryWrap.classList.remove('inactive')
    });
    
    
    $(document).ready(function() {
      let galleryWrap = $('.gallery-container')
      let scrollArea = $('.scrollable-area')
      galleryWrap.on('wheel', function(e) {
        scrolling = true;
        var scrollLeft = scrollArea.scrollLeft();
        var width = scrollArea.get(0).scrollWidth - scrollArea.width();
        var deltaY = e.originalEvent.deltaY;
        var deltaX = e.originalEvent.deltaX;
        var newScrollLeft = scrollLeft + deltaY + deltaX;
        if ((deltaY > 0 && newScrollLeft < width) ||
          (deltaY < 0 && newScrollLeft > 0)) {
          e.preventDefault();
        }
        if (newScrollLeft <= 0) {
          scrollArea.scrollLeft(0);
        } else if (newScrollLeft >= width) {
          scrollArea.scrollLeft(width);
        } else {
          scrollArea.scrollLeft(newScrollLeft);
        }
      });
    });
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    .gallery-container {
      position: relative;
      width: 100%;
      height: 250px;
      background-color: yellow;
      overflow: hidden;
    }
    
    .scrollable-area {
      width: 100%;
      height: 100%;
      overflow-x: auto;
    }
    
    .gallery-items {
      display: flex;
      min-width: 100%;
      height: 100%;
    }
    
    .gallery-item {
      flex: 0 0 auto;
      height: 100%;
      display: flex;
    }
    
    .gallery-item img {
      max-width: 100%;
      height: auto;
      object-fit: contain;
    }
    
    .gallery-item iframe {
      width: 100%;
      aspect-ratio: 16/9;
      display: block;
    }
    
    .scrollable-area {
      position: relative;
    }
    
    .gallery-container.inactive:after {
      content: "";
      position: absolute;
      display: block;
      left: 0;
      top: 0;
      right: 0;
      width: 100%;
      height: 100%;
      background: red;
      opacity: 0.1;
      z-index: 100;
    }
    <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
    
    <div class="gallery-container inactive">
      <div class="scrollable-area">
        <div class="gallery-items">
    
          <div class="gallery-item">
            <iframe frameborder="0" scrolling="no" srcdoc='<html><body style="margin:0; padding:0;"><video style="margin:0; padding:0; width:100%; aspect-ratio:16/9" controls muted playsinline controls preload="meta"><source src="https://cdn.jsdelivr.net/npm/[email protected]/video.mp4#t0" type="video/mp4"></video></html></body>'></iframe>
          </div>
    
          <div class="gallery-item">
            <img src="https://upload.wikimedia.org/wikipedia/commons/1/16/Appearance_of_sky_for_weather_forecast%2C_Dhaka%2C_Bangladesh.JPG">
          </div>
          <div class="gallery-item">
            <img src="https://upload.wikimedia.org/wikipedia/commons/d/da/Sky_landscape.jpg">
          </div>
    
          <div class="gallery-item">
            <img src="https://upload.wikimedia.org/wikipedia/commons/1/16/Appearance_of_sky_for_weather_forecast%2C_Dhaka%2C_Bangladesh.JPG">
          </div>
        </div>
      </div>
    </div>

    I’ve added a semitransparent reddish tint to illustrate the overlay toggling.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search