Implementation of CSS scroll snap event stop and element position detection

Time:2020-1-16

1、 Scroll snap is a front-end required skill

CSS scroll snap is a very useful feature. When the web page container scrolls and stops, the browser can automatically and smoothly locate to the specified location of the specified element without any JS code. Similar to the effect of slide advertising, it can be realized in pure CSS.

Moreover, CSS scroll snap is very compatible, and the mobile end can almost be used at ease.

 

2、 Scroll snap scenario from actual project

This afternoon, when implementing a functional requirement, I happened to encounter a scene that is very suitable for using scroll snap to implement, sliding and displaying personas in turn. So I used it boldly. Wow, it’s great. Without any JS to make boundary judgment, the sliding stop automatically locates to the desired position.

The key CSS codes are as follows:


ul {
    width: 375px; height: 667px;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
    overflow-y: hidden;    
}
li {
    display: inline-block;
    width: 100%; height: 100%;
    scroll-snap-align: center;
}

Scroll parent container element settingsscroll-snap-type:x mandatory, horizontal scrolling, forced positioning, sub list element settingscroll-snap-align:centerLet the list appear in the middle of the scrolling container, and the effect is achieved.

However, after the rolling positioning, you need to highlight the currently positioned character material. I find it difficult!

Before, this kind of sliding effect was implemented by JS. Whether JS animation ends or CSS animation ends, there are callback functions available. But here it is rolling, and after rolling, it will position itself for a while, and its positioning time is long or short, who knows when to stop? Sometimes you can slide multiple elements at a time, and you’re not sure which element to stop on.

In fact, standard makers and browser manufacturers are actively promoting the landing of callback events related to scroll snap, so that they can know exactly when the roll stops and which element the roll is positioned on. However, the standard is still in a state of turmoil, and the browser has not yet supported it. The project will be used now. What should we do?

Yes! Be sure to send out JS assistance.

In fact, even if it is not the use scenario of scroll snap, even ordinary scrolling, because of the inertia of scrolling, it is also a common requirement to detect whether scrolling stops. Therefore, it is necessary to smooth a method to detect when the rolling stops.

3、 My roll stop detection method

My idea is to run a timer in the rolling event to record whether the rolling distance of the current time and the last rolling distance are equal. If they are equal, the rolling is considered to have stopped. If they are not equal, the rolling is still in progress.

Using JavaScript to indicate that(This implementation has been invalidated ):

//Timer, used to detect whether horizontal scrolling is over
var timer = null;
//Last rolling distance
var scrollLeft = 0, scrollTop = 0;
//Scrolling event start
container.addEventListener('scroll', function () {
    clearInterval(timer);
    //Renew timer
    timer = setInterval(function () {
        if (container.scrollLeft == scrollLeft && container.scrollTop == scrollTop) {
            //If the rolling distance is equal, the rolling stops
            clearInterval(timer);
            //... do what you want to do, such as callback processing
        } else {
            //Otherwise, remember the last scroll position
            scrollLeft = container.scrollLeft;
            scrollTop = container.scrollTop;
        }
    }, 100);
});

If you are interested, you can further encapsulate the above code.

Updated next day

Rolling termination detection does not need to judge whether the rolling distance before and after is equal, because both inertial and snap positioning scroll events are triggered continuously. Therefore, you can do this directly:

//Timer, used to detect whether horizontal scrolling is over
var timer = null;
//Scrolling event start
container.addEventListener('scroll', function () {
    clearTimeout(timer);
    //Renew timer
    timer = setTimeout(function () {
        //No scrolling event triggered. It is considered that scrolling has stopped
        //... do what you want to do, such as callback processing
    }, 100);
});

Of course, the method provided above is not very accurate to stop detection, because the last relocation browser of scroll snap has a detection. According to my repeated research and testing, this detection event should be350ms(the actual operation may be a few milliseconds larger), which is far greater than the above setting100msTo be large, therefore, there will be a wrong redundancy judgment, which occurs before the start of snap positioning.

I think about it. This problem can’t be avoided, but it’s not a big problem. Never set400msDetection, the delay is too high, the experience is not necessarily good.

4、 Current rolling target element detection method

The principle is as follows: traverse all the list elements, and detect the left edge of the list element relative to the left edge of the scrolling container (if it is left aligned)-scroll-snap-align:left)Or center (Center) or right edge (right). Of course, if the size of the list element is the same as the size of the rolling container, the edge detection in the middle left and right can be done.

JS hints:

[].slice.call(container.children).forEach(function (ele, index) {
    if (Math.abs(ele.getBoundingClientRect().left - container.getBoundingClientRect().left) < 10) {
        //The ele element at this moment is the element currently positioned
        //... you can do what you want to do to ele
    } else {
        //The ele element at the moment is not the currently positioned element
    }
});

Strictly speaking, we should calculate whether it is equal to0, not less than10Let’s add a bit of fault tolerance.

After finishing the above two requirements that need JS assistance, the final effect will come out.

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.