What is the best way to navigate through individual child elements within a parent container that is scrollable?

I'm currently working on a unique user interface that features a scrolling list of options. The goal is for users to easily find and select the option they are looking for by simply scrolling or swiping.

However, I've encountered an issue where a single scroll movement skips multiple positions in the list. For example, if the top element displays "1" and I scroll once, I end up with "4" at the top instead of the expected "2".

The code I've implemented functions smoothly on IOS Chrome and Safari, performing exceptionally well on mobile devices.

How can I achieve the same seamless scrolling behavior on desktop browsers using CSS or JavaScript (perhaps jQuery)? Have I overlooked an error in my implementation?

Below is a snippet of basic HTML and CSS code for reference (for full-page viewing): (HTML structure can vary from divs within a div tag (as shown below), to options within a select tag, or list items within ul/ol tags)

.box {
  background-color: yellowgreen;
  height: 300px;
  overflow: hidden;
}

.scroll {
  width: 100%;
  height: 100%;
  background-color: aliceblue;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  scroll-snap-stop: always;
}

.scroll div {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  margin: 5px 0;
  padding: 10px;
  background-color: lightpink;
  scroll-snap-align: center;
}

.scroll div:first-of-type {
  margin-top: calc((50% - 20px));
}

.scroll div:last-of-type {
  margin-bottom: calc((50% - 20px));
}
<div class="box">
  <div class="scroll">
    <div>List item: 1</div>
    <div>List item: 2</div>
    <div>List item: 3</div>
    <div>List item: 4</div>
    <div>List item: 5</div>
    <div>List item: 6</div>
    <div>List item: 7</div>
    <div>List item: 8</div>
    <div>List item: 9</div>
    <div>List item: 10</div>
  </div>
</div>

Answer №1

After numerous attempts, I finally devised a solution that seems to work:

document.querySelector(".scroll").addEventListener('wheel', (e) => {
  e.preventDefault();
  if (e.deltaY < 0) {
    document.querySelector(".scroll").scrollBy({
      top: -(document.querySelector(".scroll > div").scrollHeight)
    });
  } else if (e.deltaY > 0) {
    document.querySelector(".scroll").scrollBy({
      top: (document.querySelector(".scroll > div").scrollHeight)
    });
  }
});
.box {
  background-color: yellowgreen;
  height: 300px;
  overflow: hidden;
}

.scroll {
  width: 100%;
  height: 100%;
  background-color: aliceblue;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  scroll-snap-stop: always;
}

.scroll div {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  margin: 5px 0;
  padding: 10px;
  background-color: lightpink;
  scroll-snap-align: center;
}

.scroll div:first-of-type {
  margin-top: calc((50% - 20px));
}

.scroll div:last-of-type {
  margin-bottom: calc((50% - 20px));
}
<div class="box">
  <div class="scroll">
    <div>List item: 1</div>
    <div>List item: 2</div>
    <div>List item: 3</div>
    <div>List item: 4</div>
    <div>List item: 5</div>
    <div>List item: 6</div>
    <div>List item: 7</div>
    <div>List item: 8</div>
    <div>List item: 9</div>
    <div>List item: 10</div>
  </div>
</div>

Although I'm not entirely satisfied with the functionality of the scrollBy() method's "behavior: smooth" option, this workaround may be useful for others.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JavaScript is struggling to interpret the JSON string

I am transmitting a JSON string from my Django view to a JavaScript file named idbop.js on the client side. In Django, I am utilizing the serializer to convert query results into JSON format. Here is an excerpt from my views.py file in Django: def index(r ...

A Guide to Triggering a Method Upon Component Change in Angular

When working with Angular, Components have an ngOnInit() method. I am looking for the opposite of this method. Is there a method that gets called when the component is closed? Is there a way to detect in the TypeScript file if the component is being clo ...

Tips for inverting the z-index order of stacked divs

On my webpage, I have set up multiple columns enclosed in divs like this: <div class="first column" style="width:33%; float: left;"></div> <div class="column" style="width:33%; float: left;"></div> <div class="last column" style ...

Converting a string into an array of JSON objects

I am currently attempting to send data to my NodeJS server using the HTTP protocol (vue-resource). The goal is to send an array of JSON objects structured like this : [{"name":"Charlotte","surname":"Chacha","birth":"2000-04-02"},{"name":"Michael","surname ...

What is the best way to create multiple PDF pages using mpdf1?

Currently using mpdf1 and looking to generate a PDF with a table of 4000 rows. Any suggestions on how to achieve this using mpdf1? Is there a method to speed up the process and avoid waiting for several minutes? ...

Struggling with filtering an array fetched from an API using VueJS

Currently, I am working on a Nativescript-Vue app and facing some challenges that I need help with. The Scenario I have data coming in from an API. Here is the structure of the data I receive: { "count": 9, "results": [ { "id": 1, "c ...

Is there a way to add additional outcomes to a jQuery autocomplete dropdown menu?

I have been exploring the Autocomplete plugin from jQuery documentation at http://docs.jquery.com/Plugins/Autocomplete My goal is to include two additional results that always appear at the end. Can anyone guide me on how to achieve this? ...

Creating animations with an svg mask can be effective, however, it seems to only work properly

I have been experimenting with creating a transition effect using SVG masks and CSS. Initially, everything was working as intended, but after a few repetitions (usually 1 or 2, unpredictably), the transition effect would suddenly stop and become instantane ...

When attempting to sign in or sign up on Vuex using Firebase, encountering errors such as "Cannot read property '$store' of undefined" or issues with Function CollectionReference.doc() may occur

After spending a couple of days troubleshooting, I finally identified the issue with Sign in/Sign Up on Firebase Authentication. It turned out to be a simple syntax problem and a JavaScript asynchronous issue. Error message encountered: 'Function Col ...

Create a structure for objects that can be easily cloned

Is there a way to automatically restructure a JavaScript object to be cloneable by eliminating all of its methods? In my particular scenario, I am generating three.js BufferAttribute objects in a web worker and need to transmit them to the main thread. C ...

Why is it important to incorporate an inner function in order to return to the outer function?

Can you explain the distinction between these two functions, bind_1 and bind_2? function bind_1(f, o) { if (f.bind) return f.bind(o); else return function() { return f.apply(o. arguments); }; } function bind_2(f, o) { if (f. ...

What are the best practices for implementing image-slice in node.js?

I attempted to utilize image-slice to divide an image into multiple parts using Node.js. I tried installing npm i image-to-slices, sudo port install cairo, npm i canvas, and brew install pkg-config cairo pango libpng jpeg giflib. However, I still encounte ...

Utilizing jQuery.ajax to Send an Array of Objects to a PHP Function

In this scenario, an array of objects is represented as follows: rectangle[0].width = w; rectangle[0].height = h; rectangle[1].width = w; rectangle[2].height = h; rectangle[3].width = w; rectangle[3].height = h; ... We need to figure out how to send thi ...

Problem with AngularJS factory causing issues with promises

I have a factory in AngularJS set up like this: 'use strict'; angular.module('frontRplApp') .factory('paymentService', function ($rootScope, $http, config, tools) { var urlBase = config.baseUrl; var payme ...

Tips on achieving a responsive image layout design

Trying to implement this design using Tailwind CSS and Next.js for coding this component: I'm facing challenges in achieving the desired grid layout with images, as they are not displaying properly. Below is my current approach: import Image from &a ...

Django not receiving data from AJAX GET request

I am attempting to transmit data stored in localStorage through an AJAX GET request to Django, but the Django server does not seem to receive it. I have verified that there is data in localStorage("preselection") as indicated by the output of console.log. ...

Ways to confirm the specific data in the Firebase database node

There is a JSON structure that looks like this: { "engagedUsers": { "qwe": { "agent_availability": true, "conv_id": "parthengineer_qwe", "emailId": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__ ...

How to use $refs in Vue.js to update the content of a <span> element

In my <template>, I have a <span> element with the reference span-1. <span ref="span-1">my text</span> I am trying to update the content of this <span> from my text to my new text using $refs in my <script> se ...

positioning of content on the left, right, and center

My task involves using CSS to adjust the positions of various elements on a webpage. Currently, the right position navigation bar and the liquid layout are working fine, but the positioning of the "content" and "right navigation bar" is not correct. I ai ...

Having trouble with autocompleting using jquery json and getting an Internal Server Error 500?

Why does the autocomplete program with jQuery JSON and C# work on local but not on the server? [WebMethod] public List<string> GetAutoCompleteData(string prefixText) { ... Here is the error: Internal server error 500 In addition to that, an ...