CSS scroll-snap scroll event stop and element position detection implementation

CSS scroll-snap scroll event stop and element position detection implementation

1. Scroll Snap is a must-have skill for front-end developers

CSS Scroll Snap is a very useful feature that allows the browser to automatically and smoothly locate to the specified position of the specified element when the web page container stops scrolling without the involvement of any JS code. Effects similar to slideshow advertising can be achieved with pure CSS.

Moreover, CSS Scroll Snap has excellent compatibility and can be used almost safely on mobile devices.

2. Scroll-snap scenarios from actual projects

This afternoon, when I was implementing a functional requirement, I happened to encounter a scenario that was very suitable for using Scroll Snap to implement it, sliding to display the characters in sequence. So I used it boldly, wow, it’s great, no need for any js to do boundary judgment, it will automatically position to the desired position when sliding stops.

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;
}

Set scroll-snap-type:x mandatory the scrolling parent container element, scroll horizontally, and force positioning. Set scroll-snap-align:center for the child list element to make the list appear in the middle of the scrolling container, so the effect is achieved.

However, after the scrolling positioning is completed, it is still necessary to highlight the currently positioned character material. I found this a bit difficult!

In the past, this sliding effect was implemented using JS. Whether the JS animation ended or the CSS animation ended, there was a callback function that could be used. But here it is rolling, and after rolling it will position itself for a while. The time of self-positioning varies. Who knows when it will stop? Sometimes you slide multiple elements at once and you're not sure which element to stop on.

In fact, standard setters and browser manufacturers are actively promoting the implementation of Scroll Snap related callback events, so that we can know exactly when the scrolling stops and which element the scrolling is positioned on. However, the standard is still under development and browsers do not support it yet. The project needs to be used now, what should I do?

right! JS assistance must be used.

In fact, even if it is not the usage scenario of Scroll Snap, even if it is ordinary scrolling, due to the inertia of scrolling, detecting whether the scrolling has stopped is also a common requirement. Therefore, it is necessary to come up with a method to detect when the scrolling stops.

3. My scrolling suspension detection method

To detect whether the scrolling of an element has stopped, my implementation idea is to run a timer in the scrolling event to record whether the scrolling distance at the current time is equal to the distance of the previous scrolling. If they are equal, it is considered that the scrolling has stopped. If they are not equal, it is considered that the scrolling is still in progress.

The JavaScript representation is ( this implementation is deprecated ):

// Timer, used to detect whether horizontal scrolling has ended var timer = null;
// The last scroll distance var scrollLeft = 0, scrollTop = 0;
// Scroll event starts container.addEventListener('scroll', function () {
    clearInterval(timer);
    // Reset the timer timer = setInterval(function () {
        if (container.scrollLeft == scrollLeft && container.scrollTop == scrollTop) {
            // When the scrolling distance is equal, it is considered that the scrolling has stopped clearInterval(timer);
            // ... do whatever you want, such as callback processing } else {
            // Otherwise, still remember the last scroll position scrollLeft = container.scrollLeft;
            scrollTop = container.scrollTop;
        }
    }, 100);
});

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

Updated on the next day

Scroll termination detection does not need to determine whether the previous and next scrolling distances are equal, because both inertial and Snap positioning scroll events are continuously triggered. Therefore, it is possible to directly:

// Timer, used to detect whether horizontal scrolling has ended var timer = null;
// Scroll event starts container.addEventListener('scroll', function () {
    clearTimeout(timer);
    // Reset the timer timer = setTimeout(function () {
        // No scroll event is triggered, so scrolling is considered stopped // ... do what you want to do, such as callback processing }, 100);
});

Of course, the method provided above is not a very accurate termination detection, because the browser itself has a detection for the final repositioning of Scroll Snap. According to my repeated research and tests, this detection event should be 350ms (the actual operation may be slightly larger by a few milliseconds), which is much larger than 100ms set above. Therefore, there will be an erroneous redundant judgment that occurs before the Snap positioning starts.

I thought about it and realized that this problem is unavoidable, but it is not a big problem. It is impossible to set the detection time to 400ms . The delay is too high and the experience may not be good.

4. Current scroll target element detection method

The principle is as follows, iterate over all list elements and detect the position of the left edge of the list element relative to the left edge of the scroll container (if it is left-aligned - scroll-snap-align:left ) or the center (center alignment) or the right edge (right alignment). Of course, if the list element size is consistent with the scroll container size, left, center, and right edge detection are both acceptable.

JS indicates:

[].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 currently positioned element // ... you can do what you want with ele } else {
        // The ele element at this moment is not the currently positioned element}
});

Strictly speaking, we should calculate whether it is equal to 0 , not less than 10 Here, we add a tolerance interval.

After solving the above two requirements that require JS assistance, the final effect is achieved.

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

<<:  How to connect Navicat to the docker database on the server

>>:  How to implement CSS to display ellipsis when single-line or multi-line text overflows

Recommend

Detailed explanation of using Docker to build externally accessible MySQL

Install MySQL 8.0 docker run -p 63306:3306 -e MYS...

Docker exec executes multiple commands

The docker exec command can execute commands in a...

How to elegantly implement the mobile login and registration module in vue3

Table of contents Preface Input box component lay...

MySQL 5.7.18 version free installation configuration tutorial

MySQL is divided into installation version and fr...

Solution to large line spacing (5 pixels more in IE)

Copy code The code is as follows: li {width:300px...

Innodb system table space maintenance method

Environmental Description: There is a running MyS...

Vue.js $refs usage case explanation

Despite props and events, sometimes you still nee...

Loading animation implemented with CSS3

Achieve results Implementation Code <h1>123...

Vue.js handles Icon icons through components

Icon icon processing solution The goal of this re...

The shortest JS to determine whether it is IE6 (IE writing method)

Commonly used JavaScript code to detect which ver...

Detailed explanation of the solution to docker-compose being too slow

There is only one solution, that is to change the...

Working principle and implementation method of Vue instruction

Introduction to Vue The current era of big front-...

Detailed explanation of MySQL joint query optimization mechanism

Table of contents MySQL federated query execution...

MySQL installation diagram summary

MySQL 5.5 installation and configuration method g...

mysql 5.7.17 winx64.zip installation and configuration method graphic tutorial

Preface: I reinstalled win10 and organized the fi...