8

No matter if I change the scroll-snap-type or the scroll-snap-align, Safari looses the scroll position and starts from first scroll-snap element. This problem can be easily reproduced in the scroll example here: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type. Just switch to scroll-snap-type: mandatory, scroll to 2nd or 3rd element. Then switch to scroll-snap-type: none and back again to scroll-snap-type: mandatory. In all browsers the scroll position stays the same, in Safari it starts again from 0.

Why do I need this? I am using a scroll animation that changes the scrollTop position. When using scroll-snap in Safari the animation does not work e.g. when click on a navigation link to scroll to another section. So my idea was to turn scroll-snap off when using a navigation link and turn it on again when done. Works fine in all browsers, leads to described problem in Safari. I also tried to change the scroll-snap-align instead, but its the same.

Did someone experience the same problem? Did you find a workaround / solution?

hummh
  • 131
  • 4

4 Answers4

2

Same problem here - may I ask if you have found a solution? Mine is to simply disable scroll-snapping for Safari, with the impact of less user-comfort ... written in less:

scroll-snap-type: y mandatory; // vertical scroll-snap
@media not all and (min-resolution:.001dpcm) { // detect Safari
    scroll-snap-type: unset;
}
  • In the end I turned off scroll snapping in Javascript before the scroll animation starts and turned it on again when scroll animation ends. I would consider this more as a workaround than a proper solution. – hummh Jun 05 '21 at 08:04
2

I encountered the same problem. What finally worked for me was to set overflow: hidden on the element while you're changing the scroll-snap-type. This prevents the container from being manually scrolled, and also seems to prevent Safari from resetting the scroll position. Once the scroll animation is complete, you can restore the scroll-snap-type and remove overflow: hidden.

I did this by creating a new class:

.disable-snapping
  overflow: hidden;
  scroll-snap-type: none;

And the exact steps that worked for me are:

  1. Before the scroll animation starts, add the disable-snapping class to the scrollable container.
  2. Do the scroll animation.
  3. Once the animation is complete, remove the disable-snapping class.
Clint
  • 21
  • 2
1

I experienced the same, because I wanted to implement dragging. I decided to lose the dragging functionality. I fixed your problem with scroll-behavior: smooth; and used anchor links.

You can find my code here: https://codepen.io/joosts/pen/MWJBPgo?editors=0110

Mr. Hugo
  • 11,887
  • 3
  • 42
  • 60
1

Just encountered the same problem. Very annoying.. But resetting the scroll position after re-enabling the scroll-snap behavior works surprisingly well.

const onDragEnd = () => {
    const scroller = $('.scroll-container');
    const scrollLeft = scroller.scrollLeft();
    scroller.removeClass('drag-in-progress'); // this class disabled scroll-snapping
    requestAnimationFrame(() => scroller.scrollLeft(scrollLeft));
};

Jesse
  • 422
  • 3
  • 19