Mobile URL bar resizing makes autoplaying carousel (Keen-Slider) to jump to the edge of a slide on initial scroll

I have an autoplaying, smooth carousel, which isis also draggable on desktop. To achieve this I use Keen-Slider. And this all works how I need it to when viewing in a desktop browser.

The problem I have occurs when viewing the page on my mobile device (iPhone 15). Tested on iOS in Safari and Chrome. Initially the page loads and behaves as expected and if left untouched will continue to do so.

The Problem

However as soon as I scroll down the page a pixel or two, the carousel will ‘jump’ to the edge of one of the slides within it – I assume this is the closest one to the left edge of the page. Almost like it’s snapping to the nearest slide after scroll.

The Cause

It’s taken me a bit to figure out why but I’m positive this is down to the Mobile Address Bars resizing as you begin to scroll.

This only happens on the first scroll though! After that, you can scroll up/down as much as you like with the Address Bar resizing and the carousel will continue to behave as intended. Almost like it needs that first scroll to recognise the behaviour.

So I think I’ve got to the bottom of the cause of the issue – but now I can’t find a way to fix it.

Thanks in advance and really hope someone can help with this!

/* ==========================================================================
   #LAZY LOAD IMAGES
   ========================================================================== */

/**
 * Class to animate/transition an image into view once it has been loaded.
 */

const pixelImage = document.querySelectorAll(".pixel-load")

const observer = new IntersectionObserver(
    entries => {
        entries.forEach(entry => {
            
            const img = document.querySelector(".pixel-load > img")
                        
            function loaded() {
                entry.target.classList.toggle("loaded", entry.isIntersecting)
            }
            
            if (img.complete) {
                loaded()
            } else {
                img.addEventListener("load", loaded)
            }
            
            if (entry.isIntersecting) observer.unobserve(entry.target)
        })
    },
    {
        threshold: 0
    }
)

pixelImage.forEach(image => {
    observer.observe(image)
})




/* ==========================================================================
   #KEEN SLIDER
   ========================================================================== */

/**
 * Using Keen-Slider for the infinite looping carousel, which I originally did
 * in pure CSS - but I wanted to make this draggable by the user so made sense
 * to use a 3rd party plug-in to do the heavy lifting.
 */

var animation = {
  duration: 32000,
  easing: (t) => t
}
new KeenSlider("#gallery-slider", {
  dragSpeed: 1,
  loop: true,
  mode: "free",
  slides: {
    perView: 1.5,
    renderMode: "performance",
    spacing: 8
  },
  breakpoints: {
    '(min-width: 768px)': {
      slides: {
        perView: 3,
        spacing: 8
      }
    },
    '(min-width: 1024px)': {
      slides: {
        perView: 4,
        spacing: 8
      }
    }
  },
  created(s) {
    s.moveToIdx(5, true, animation)
  },
  updated(s) {
    s.moveToIdx(s.track.details.abs + 5, true, animation)
  },
  animationEnded(s) {
    s.moveToIdx(s.track.details.abs + 5, true, animation)
  }
})
/* ==========================================================================
   #BASE
   ========================================================================== */

html {
  font-size: 62.5%;
  margin: 0;
  padding: 0;
}

body {
  font-size: 12px;
  font-family: "Arial", sans-serif;
  margin: 0;
  padding: 128px 0 0;
  text-transform: uppercase;
}

h2 {
  font-size: 12px;
  font-weight: 400;
  margin: 0 16px 16px;
  padding: 0;
}

p {
  margin: 0 16px 128px;
}

figure {
  margin: 0;
  padding: 0;
}

img {
  height: auto;
  width: 100%;
  max-width: 100%;
}


/* ==========================================================================
   #KEEN SLIDER
   ========================================================================== */

.keen-slider:not([data-keen-slider-disabled]) {
  display: flex;
  align-content: flex-start;
  overflow: hidden;
  position: relative;
  touch-action: pan-y;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  width: 100%;
  -webkit-tap-highlight-color: transparent;
}

.keen-slider:not([data-keen-slider-disabled]) .keen-slider__slide {
  min-height: 100%;
  overflow: hidden;
  position: relative;
  width: 100%;
}

.keen-slider:not([data-keen-slider-disabled])[data-keen-slider-v] {
  flex-wrap: wrap;
}




/* ==========================================================================
   #GALLERY
   ========================================================================== */
   
/**
 * My overrides for the Keen Slider gallery.
 *
 * 1. Remove `overflow: hidden` from the slider and add it to the parent. This
 *    allows the slider to align with the grid but also bleed off the edges of
 *    the page.
 * 2. Align container with the global grid.
 */

.gallery {
    margin-bottom: 128px;
    overflow: hidden; /* [1] */
    padding: 0 16px; /* [2] */
}

.gallery .keen-slider {
  overflow: visible; /* [1] */
}

/**
 * As the widths for each slide are set in Javascript. We add widths to slides
 * before `.keen-slider` has loaded to keep the layout consistent and help with
 * the Cumulative Layout Shift (CLS) and performance.
 */

#gallery-slider:not(.loaded) .keen-slider__slide {
  width: calc((100vw / 1.5) - 24px);
}

@media(min-width: 48em) {
  .keen-slider:not(.loaded) .keen-slider__slide {
    width: calc((100vw - 48px) / 3);
  }
}

@media(min-width: 64rem) {
  .keen-slider:not(.loaded) .keen-slider__slide {
    width: calc((100vw - 56px) / 4);
  }
}




/* ==========================================================================
   #PIXEL LOAD
   ========================================================================== */

/**
 * Add a pixelated effect to images while the load.
 */

.pixel-load {
  overflow: hidden;
  position: relative;
}

.pixel-load__preload img {
  image-rendering: pixelated;
  position: absolute;
  inset: 0;
  opacity: 1;
  pointer-events: none;
}

.loaded .pixel-load__preload img {
  animation: loaded 0.32s 0.32s steps(1, end) both;
}

@keyframes loaded {
  0% {
    scale: 1.1;
  }
  64% {
    scale: 1.04;
  }
  75% {
    opacity: 0.8;
    scale: 1.02;
  }
  100% {
    opacity: 0;
    z-index: 1;
  }
}
<html>

<body>

  <h2>Placeholder text to push content down and create vertical scroll</h2>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat /questions/ask#non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

  <!-- Keen Slider -->
  <div class="gallery">
    <div id="gallery-slider" class="keen-slider">
      <div class="keen-slider__slide">
        <figure data-label="Hover Label 1" class="has-label">
          <div class="pixel-load">
            <div class="pixel-load__preload">
              <img src="https://placebeard.it/18/24" width="18" height="24">
            </div>
            <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
          </div>
          <figcaption>Slide 1</figcaption>
        </figure>
      </div>
      <div class="keen-slider__slide">
        <figure data-label="Hover Label 2" class="has-label">
          <div class="pixel-load">
            <div class="pixel-load__preload">
              <img src="https://placebeard.it/18/24" width="18" height="24">
            </div>
            <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
          </div>
          <figcaption>Slide 2</figcaption>
        </figure>
      </div>
      <div class="keen-slider__slide">
        <figure data-label="Hover Label 3" class="has-label">
          <div class="pixel-load">
            <div class="pixel-load__preload">
              <img src="https://placebeard.it/18/24" width="18" height="24">
            </div>
            <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
          </div>
          <figcaption>Slide 3</figcaption>
        </figure>
      </div>
      <div class="keen-slider__slide">
        <figure data-label="Hover Label 4" class="has-label">
          <div class="pixel-load">
            <div class="pixel-load__preload">
              <img src="https://placebeard.it/18/24" width="18" height="24">
            </div>
            <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
          </div>
          <figcaption>Slide 4</figcaption>
        </figure>
      </div>
      <div class="keen-slider__slide">
        <figure data-label="Hover Label 5" class="has-label">
          <div class="pixel-load">
            <div class="pixel-load__preload">
              <img src="https://placebeard.it/18/24" width="18" height="24">
            </div>
            <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
          </div>
          <figcaption>Slide 5</figcaption>
        </figure>
      </div>
      <div class="keen-slider__slide">
        <figure data-label="Hover Label 6" class="has-label">
          <div class="pixel-load">
            <div class="pixel-load__preload">
              <img src="https://placebeard.it/18/24" width="18" height="24">
            </div>
            <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
          </div>
          <figcaption>Slide 6</figcaption>
        </figure>
      </div>
      <div class="keen-slider__slide">
        <figure data-label="Hover Label 7" class="has-label">
          <div class="pixel-load">
            <div class="pixel-load__preload">
              <img src="https://placebeard.it/18/24" width="18" height="24">
            </div>
            <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
          </div>
          <figcaption>Slide 7</figcaption>
        </figure>
      </div>
      <div class="keen-slider__slide">
        <figure data-label="Hover Label 8" class="has-label">
          <div class="pixel-load">
            <div class="pixel-load__preload">
              <img src="https://placebeard.it/18/24" width="18" height="24">
            </div>
            <img src="https://placebeard.it/768/1024" width="768" height="1024" loading="lazy" />
          </div>
          <figcaption>Slide 8</figcaption>
        </figure>
      </div>
    </div>
    <!-- End Keen Slider -->

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/keen-slider.min.js"></script>


</body>

</html>

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật