Question Details

No question body available.

Tags

javascript html css

Answers (3)

Accepted Answer Available
Accepted Answer
July 23, 2026 Score: 2 Rep: 858 Quality: High Completeness: 80%

const list = document.querySelector('.list');
const items = Array.from(document.querySelectorAll('.item'));

const observer = new IntersectionObserver(onIntersectionObserved, { root: list, threshold: 0.55, });

items.forEach(item => { observer.observe(item); });

function onIntersectionObserved(entries) { entries.forEach(entry => { if (entry.isIntersecting) { const intersectingIndex = items.indexOf(entry.target); } }); }

.list {
  width: 100%;
  display: flex;
  height: 750px;
  overflow-x: scroll;
  overscroll-behavior-x: contain;
  overscroll-behavior-y: auto;  
  align-items: center;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-x pan-y;
  scroll-snap-type: x mandatory;
}

.list::-webkit-scrollbar { display: none; }

.item { margin-left: 15%; margin-right: 15%; margin-bottom: 25px; height: 700px; flex: 0 0 70%; box-sizing: border-box; width: 100%; background-color: #8cbde6; border-radius: 30px; z-index: 5; display: flex; position: relative; outline: 10px solid #587c99; scroll-snap-align: center; scroll-snap-stop: always; }

.viewport { background: #ffffff; width: 100%; height: 1500px; position: relative; top: 25px; overflow-x: hidden; overflow-y: auto; z-index: 0; }


        

Okay this is what happens.

You have set overflow-x: scroll on .list. But overflow-y unset (visible). Pers CSS Overflow level 3, when one azxis is non visible the other computes from visible to auto. The .list is therefore a scroll conatiner on both axes.

Content height (700px item + 25px margin) is under the 750px container height, so there is no verticle scrollable overflow. scrollTop is permenantly 0. It's like simultaneously at the start and end boundary.

overscroll-behavior is a shorthand setting both x and y. MDN states

A scroll container that has no scrollable overflow, such as an element with overflow: hidden, is always considered to be at its scroll boundary. So setting a non-default overscroll-behavior such as contain or none on it will prevent scroll chaining to ancestor scroll containers.

So the result is verticle event hit, tests to .list, but .'list cannot consume it, and contain on the y axis suppresses propagation to .viewport (or document). Dead zone on mouse.

So the fix is

.list { touch-action: pan-x pan-y; / restores vertical touch gestures / overscroll-behavior-x: contain; / keep: blocks horizontal swipe-back navigation / overscroll-behavior-y: auto; / restores vertical wheel chaining to the page / }
July 23, 2026 Score: 1 Rep: 370 Quality: Low Completeness: 80%

.list is blocking the vertical gesture because it is declared as a horizontal-only touch target with touch-action: pan-x.

Remove that rule, or set it back to auto, so vertical pans can be handled by the page/parent scroller. Do not use the shorthand overscroll-behavior: contain here if you only want to contain horizontal overscroll; that applies containment to both axes. Use the x-axis property instead.

Close the ul; the browser will repair this, but the markup should be valid:

touch-action controls which touch gestures the browser handles, and overscroll-behavior controls whether scrolling chains to an ancestor scroll container.

.list {
  width: 100%;
  display: flex;
  height: 750px;
  overflow-x: auto;

/ contain only horizontal overscroll / overscroll-behavior-x: contain; overscroll-behavior-y: auto;

align-items: center; scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch;

/ allow vertical page scrolling from touches that start on .list / touch-action: auto; / or remove this line /

scroll-snap-type: x mandatory; }

.item { margin-left: 15%; margin-right: 15%; margin-bottom: 25px; height: 700px; flex: 0 0 70%; box-sizing: border-box; width: 100%; background-color: #8cbde6; border-radius: 30px; z-index: 5; display: flex; position: relative; outline: 10px solid #587c99; scroll-snap-align: center; scroll-snap-stop: always; }

.viewport { background: #ffffff; width: 100%; height: 1500px; position: relative; top: 25px; overflow-x: hidden; overflow-y: auto; z-index: 0; }

July 23, 2026 Score: -1 Rep: 1 Quality: Low Completeness: 80%

Add this JavaScript right after your existing code:

const list = document.querySelector('.list');

list.addEventListener('wheel', (e) => { // If user is scrolling vertically, let the parent (.viewport) handle it if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) { e.stopPropagation(); // Allow vertical scroll to bubble up } }, { passive: true });

Even shorter

document.querySelector('.list').addEventListener('wheel', e => { if (e.deltaY !== 0) e.stopPropagation(); }, { passive: true });
  • Your .list is consuming all wheel events because of overflow-x: scroll.

  • This code detects vertical wheel movement and stops the event from being fully captured by the horizontal scroller, allowing the .viewport to scroll vertically.

Bonus:

.list { // other css overscroll-behavior-y: none; / Prevents weird bounce / touch-action: pan-x pan-y; / Better touch support / }