Utilizing CSS for Horizontal Scroll-Snap-Type

My website utilizes Bootstrap 4, horizontal scrolling (with the help of jquery.mousewheel.js), and native CSS Snapping. I am using Chrome 81 and do not concern myself with old or unsupported browsers.

The issue arises when I add scroll-snap-type: x mandatory; to the CSS - the horizontal scrolling ceases to function altogether. Removing this CSS property restores normal scrolling behavior. Below is the structure of my HTML:

<div class="portfolio_content container-fluid h-100">
  <div class="row h-100 flex-row flex-nowrap scrollx long_content">
    <div class="col-12 h-100 project d-table" id="project1">
      <div class="project_title d-table-cell align-middle">
        <p>
          Project 1
        </p>
      </div>
    </div>
    <div class="col-12 h-100 project d-table" id="project2">
      <div class="project_title d-table-cell align-middle">
        <p>
          Project 2
        </p>
      </div>
    </div>
    <div class="col-12 h-100 project d-table" id="project3">
      <div class="project_title d-table-cell align-middle">
        <p>
          Project 3
        </p>
      </div>
    </div>
    <div class="col-12 h-100 project d-table" id="project4">
      <div class="project_title d-table-cell align-middle">
        <p>
          Project 4
        </p>
      </div>
    </div>
  </div>
</div>

Here are the crucial entries in the CSS:

html, body {
    height: 100%;
}
.portfolio_content .scrollx {
    overflow-x: scroll;
}

.portfolio_content .long_content {
    scroll-snap-type: x mandatory; /* Disabling this allows for scrolling */
}
.portfolio_content .project {
    scroll-snap-align: start;
}
.portfolio_content .project_title {
    display: block;
    margin: auto;
    text-align: center;
}
.portfolio_content .project_title h1 {
    font-size: 96px;
    line-height: 0.8;
}

Lastly, here is the JSFiddle demo. By commenting out line 9 in the CSS, the demo regains its scrolling functionality.

My objective is to ensure that each "project" DIV snaps into view when scrolling, displaying one complete "project" DIV at a time.

How can I modify the code to achieve this?

Answer №1

Why rely on an external plugin when you can achieve the same with a simple script?

$(".portfolio_content .project").on('wheel', function(e) {
    e.preventDefault();        
    if (e.originalEvent.wheelDelta >= 0) {
        if ($(this).prev().length) {
            var prev = "#" + $(this).prev().attr("id");
            document.querySelector(prev).scrollIntoView({behavior: 'smooth'});
        }
    } else {
        if ($(this).next().length) {
            var next = "#" + $(this).next().attr("id");
            document.querySelector(next).scrollIntoView({behavior: 'smooth'});
        }
    }
});
html, body {
    height: 100%;
}
.portfolio_content .scrollx {
    overflow-x: scroll;
}

.portfolio_content .project {
scroll-snap-align: start;
}
.portfolio_content .project_title {
display: block;
margin: auto;
text-align: center;
}
.portfolio_content .project_title h1 {
font-size: 96px;
line-height: 0.8;
}
#project1, #project3 {
    background-color: #EEE;
}
#project2, #project4 {
    background-color: #CCC;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d0a0bfa0a0b5a2febaa390e1fee1e6fee0">[email protected]</a>/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

<div class="portfolio_content container-fluid h-100">
  <div class="row h-100 flex-row flex-nowrap scrollx long_content">
    <div class="col-12 h-100 project d-table" id="project1">
      <div class="project_title d-table-cell align-middle">
        <p>
          Project 1
        </p>
      </div>
    </div>
    <div class="col-12 h-100 project d-table" id="project2">
      <div class="project_title d-table-cell align-middle">
        <p>
          Project 2
        </p>
      </div>
    </div>
    <div class="col-12 h-100 project d-table" id="project3">
      <div class="project_title d-table-cell align-middle">
        <p>
          Project 3
        </p>
      </div>
    </div>
    <div class="col-12 h-100 project d-table" id="project4">
      <div class="project_title d-table-cell align-middle">
        <p>
          Project 4
        </p>
      </div>
    </div>
  </div>
</div>

Answer №2

To successfully convert the mousewheel delta from X to Y, you must then apply it to the specific element that contains the scrollbar. It is crucial to also prevent the default behavior when interacting with the vertical mousewheel within the container. Make sure to set the width of the container correctly in order to ensure proper functionality.

 // Scroll horizontally using the mouse wheel:
const scrollableContainer = document.querySelector('.long_content');

scrollableContainer.addEventListener('wheel', (event) => {

event.preventDefault(); 

// Determine scroll direction
let delta = event.deltaY;

// Obtain the width of the container:
let containerWidth = evt.target.offsetWidth;

// Check the direction and adjust the container width accordingly
if(delta < 0){
containerWidth = -containerWidth;
}
     
  scrollableContainer.scrollLeft += containerWidth;  

});

Link to the revised JSFiddle demonstration

Answer №3

Simply put: remove the javascript code.

If you are looking to just let the browser handle scrolling without interference, then mousewheel.js may not be necessary for your needs. By blocking the default action in the function, you are essentially preventing the browser from executing its intended scroll behavior.

By using this.scrollLeft -= delta;, you are triggering both a scroll and an end scroll event. The scroll-snap-type is designed to respond to the end scroll event by snapping the element into place. Removing only the e.preventDefault(); line can result in a jittery behavior of the element before it settles back in position. This happens because of conflicting signals being sent during the scroll process.

In order to achieve the desired behavior, it is recommended to allow the browser to handle scrolling naturally. If you wish to implement custom actions, consider modifying the code within the mousewheel function accordingly.

After considering feedback:

If the goal is to convert vertical wheel events into horizontal ones, alternative approaches may be needed. One suggestion is to cancel the original event and create a synthetic WheelEvent. Another option is to utilize scrollBy with the smooth behavior for improved functionality.

Additional thoughts:

While there are multiple strategies available, each comes with its own drawbacks. Experimenting with different solutions like the one provided in the second fiddle may lead to the desired outcome, but fine-tuning may be required. It's important to note that not all methods will work universally across browsers, and some features like event simulation in mousewheel.js may currently have limitations.

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

What is the reason for the Client Height value not affecting other elements?

I'm trying to set the spacing of my sidebar from the top equal to the height of the header. However, when I use clientHeight in JavaScript to get the height and then try to apply it to other elements using marginTop or top values (with position includ ...

PHP AJAX 12017 Issue with Header(Location:) Redirection

My problem involves a jQuery function that utilizes AJAX to call a PHP file. In the PHP file, I have included the following code snippet: header('Location: http://www.google.com'); Unfortunately, this method does not successfully redirect the ...

Struggling with jQuery UI Draggable 1.10.3 bug in Firefox: Cursor center not detected when scrolling window

Before version 1.10.3, possibly 1.9.x, I didn't encounter this issue. However, after updating to jQuery UI 1.10.3, Firefox seems to have trouble locating the center of the cursor on the draggable plugin when the window is scrolled down. This problem ...

Mastering CSS selectors with jQuery

My desire to delve into the world of jQuery has ignited. From my perspective, jQuery simply selects the desired element and performs actions on it. However, I find the selection process closely resembling CSS selectors, a realm with which I am not well-ver ...

Retrieve the value of the nested list item along with the value of its parent unordered list in a JSON format by

Having trouble getting the correct values for my unordered list and li elements within it. I have tried multiple resources, such as: http://jsfiddle.net/mohammadwali/tkhb5/ how-do-i-convert-the-items-of-an-li-into-a-json-object-using-jquery jquery-tree- ...

Problem arises when attempting to display a div after clicking on a hyperlink

I'm encountering an issue with displaying a div after clicking on a link. Upon clicking one of the links within the initial div, a new div is supposed to appear below it. All tests conducted in jsfiddle have shown successful results, but upon transf ...

CSS: Dynamically adjusting height based on parent element's current height

I'm seeking clarification on the topic at hand. Why am I unable to simply use the following code: <div style="min-height: 100vh"> <div style="height: 100%"> </div> </div> When I implement this code, ...

Utilizing cross-domain AJAX for JSON requests

I'm currently on the website site.com attempting to retrieve some JSON data from my node.js server running on port 8080. Encountered this particular error message: XMLHttpRequest cannot load http://site.com:8080/json/1. Origin http://site.com is not ...

Achieving font preloading compatibility across all browsers

Despite the abundance of resources on properly preloading fonts, I have yet to find a solution that works seamlessly on both Firefox and Chrome. My current method includes: <link rel="preload" href="URL" as="font" type=&qu ...

The inconsistency in div sizes may be attributed to the line-height setting

I'm trying to get two divs to sit next to each other and be aligned at the bottom. However, when I add a button and set the line-height, it drops slightly. See examples with images below. My Desired Layout: https://i.sstatic.net/MZQvg.png Current I ...

The jQuery .ajax function encounters an error if the input value of '0' is used

I have developed a number guessing game using jQuery and PHP, which is working well for all numbers except 0. For some reason, the Ajax call fails when 0 is entered as the guess. I suspect that the variable $guess sent to the server-side code is not being ...

Is it possible to store a $variable of $variable in session using PHP?

Welcome to my web page dedicated to searching for the scientific names of plants. Simply type the plant name in the search bar and you will see live results just like the search bars on Google or Facebook. For example, if you type "C" in the search input, ...

Deactivate the current session by choosing an item from the drop-down menu

I'm looking to incorporate an option in my dropdown menu that unsets or destroys the session $_SESSION['selected_opt]. Sample code: <form class="search-form"> <select name="thema" class="selectpicker"> <option value=" ...

Menu options

I am currently working on developing a mouseover navigation website. Initially, my design included main buttons for "Our Team", Locations, and Patient Resources. Here is the basic structure I had before attempting to switch to a mouseover approach... &l ...

I am facing an issue with my $.getJSON() script not functioning as expected

Having trouble getting my JSON / AJAX script to work. I've searched everywhere but can't find a clear explanation of how to use $.getJSON. Can someone please help me out and explain why my code isn't functioning? I suspect the issue lies wit ...

Comparison of single-line and multi-line CSS styles placement

There seems to be a debate among CSS developers regarding the preference for multi-line or single-line formatting. Some argue that multi-line is favored for its ease in finding specific properties within the CSS file. However, others believe that single- ...

Implement a dynamic loading feature using AJAX, pushState, and Jekyll for a

In an effort to create a standard template for our studio's Jekyll sites development, I am aiming to implement page animation transitions. My plan involves loading different content from each page using AJAX and utilizing pushState to update the URL a ...

Using jQuery to load an image into a div and smoothly fade it in

I am currently working on creating a gallery and I am facing an issue with loading an image into a div. The problem arises when I try to apply a fade effect after the image has finished loading. If I remove the display:none property, the image does load in ...

css troubleshooting problem: div element floating

When resizing the browser, I am aiming to achieve the layout displayed in the second image without encountering the positioning of the first image. http://jsfiddle.net/gtczu/19/ <div id="lft-widget" style=" border:solid red 3px"></div> <div ...

Centering an icon in tandem with Typography text using Material UI

Is there a way to align an icon with the text so that they are on the same level? Currently, it seems like the icon is slightly above the text. I've tried using padding-top: 5px and margin-top: 5px, but those solutions didn't work as expected. ...