Turn off all pointer events on the overlaying div but keep scrolling enabled

Issue:

I am facing a problem with two containers that have overflowing text content like this: https://i.sstatic.net/wsasV.png

In this setup, the blue <div>s have overflow:hidden applied. Now, I am trying to synchronize the scrolling behavior of these divs in a customized manner, regardless of where I scroll within the white container <div>. My idea is to create a transparent, absolutely positioned <div> directly inside the white container and allow it to have overflowing children:

https://i.sstatic.net/06k1a.png

The blue container in this setup has a higher z-index compared to the original two text containers:

.container {
  width: 100vw;
  height: 100vh;
  z-index: 10;
  position: absolute;
  overflow-y: scroll;
}

This leads to a final visual result like this:

https://i.sstatic.net/32jK5.png

My aim is to be able to scroll the overlay container while still capturing other mouse events (like text selection) in the underlying elements.

What I am trying to achieve is similar to Perforce P4Merge's diff tool, where they have a single vertical scrollbar for two code blocks, allowing scrolling based on the content discrepancy between the two blocks.

Concern:

Considering the limitation that we cannot selectively disable pointer events using the CSS property pointer-events, is there an alternative method to enable only the scroll event of the overlaying element while redirecting other pointer events to the underlying elements?

Insight:

In the original implementation written in React, I noticed that there was no need for margin-left: -18px; on the scrollable-container to display the scrollbar, which is intriguing. Additionally, here is a Codepen snippet for reference: codepen snippet

Answer №1

If you happen to come across this old question and are in need of a similar solution, here is what I discovered. I implemented a java script event listener to temporarily disable pointer-events on mousedown and then re-enable the pointer event on mouse up for its parent element.

function addlistener() {
  var scrollable = document.getElementsByClassName("scrollable-container")[0];
  scrollable.addEventListener('mousedown', function() {
    this.style.pointerEvents = "none";
    document.elementFromPoint(event.clientX, event.clientY).click();
  }, false);

  document.getElementsByClassName("app")[0].addEventListener('mouseup', function(e) {
    scrollable.style.pointerEvents = "all";
  }, false);
}
body {
  overflow-y: hidden;
}

.app {
  overflow-y: hidden;
  position: relative;
  display: flex;
  flex-direction: row;
  z-index: 0;
}

.scrollable-container {
  width: 100vw;
  height: 100vh;
  margin-left: -18px;
  position: absolute;
  overflow-y: scroll;
  z-index: 10;
}

.scrollable-content {
  width: 500px;
  height: 1600px;
}

.non-scrollable-container {
  flex: 1;
  height: 100vh;
  overflow-y: hidden;
}

.bridge {
  width: 40px;
  background: linear-gradient(white, black);
  cursor: ew-resize;
  height: 100vh;
}

#original {
  background: linear-gradient(red, yellow);
  height: 2100px;
}

#modified {
  background: linear-gradient(blue, green);
  height: 1600px;
}
<body onload="addlistener()">
  <div class="app">
    <div class="scrollable-container">
      <div class="scrollable-content"></div>
    </div>
    <div class="non-scrollable-container">
      <div id="original" class="codeBlock">
        Content I want to select
      </div>
    </div>
    <div class="bridge"></div>
    <div class="non-scrollable-container">
      <div id="modified" class="codeBlock">
        Content I want to select
      </div>
    </div>
  </div>
</body>

Answer №2

After spending a few days researching, it appears that achieving my desired outcome in the current manner is not feasible. There doesn't seem to be a way to selectively disable pointer events, and I haven't found a workaround.

Instead, I have devised an alternative solution by implementing a custom "fake" scrollbar. This scrollbar implementation listens to the container's `wheel` event and synchronizes the scroll positions of child containers. I'll keep this question open without accepting an answer, in case a better solution is suggested.

For those interested, you can view my solution below. Note: For an improved experience, select Full Page view.

let appStyles = {
original: {
background: 'linear-gradient(red, yellow)',
height: '1600px',
},
modified: {
background: 'linear-gradient(blue, green)',
height: '2100px',
},
};

// More code goes here...

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
body {
  margin: 0;
overflow-y: hidden;
}

.app {
  display: flex;
  flex-direction: row;
}

.code {
  margin: 0;
}
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root">
  
</div>

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

Selecting a main node using the key value

Is there a way to select the root node of a d3.hierarchy based on a specific JSON key value? For instance, instead of having "A1" as the root node in the given JSON object, can we make "B1" the root node by referencing its name value? { "name": "A1", ...

Showing JSON information in an Angular application

Upon page load, I am encountering an issue with retrieving and storing JSON data objects in Angular scope for use on my page and in my controller. When attempting to access the value, I receive the error message: angular.js:11655 ReferenceError: data is ...

"Upgrade your uploading experience with Fine Uploader 3.0 to easily customize PHP filenames post-upload

After uploading a file with a PHP script that changes the file name to an md5 value, I am having trouble retrieving the new file name. Fine Uploader, however, displays the original file name that was uploaded from the PC. I am looking for a way to retrieve ...

Queueing up file downloads through a web browser

When trying to download multiple files from a server, I am required to queue them up instead of downloading in parallel. Unfortunately, I do not have access to the download server, so my only option is to work with the browser. Is there an API available t ...

Transfer the value of a variable within the local scope to the dragstart event handler during the dynamic generation of an input element

After going through several similar questions, I couldn't find a solution that applies to my specific case. Here is the loop I am working with: $.each(data.modules, function(i, field) { let $li = $(`<li><div> Name: ${field.name}</div& ...

Begin the process of setting up PDF.js on the website

I've been attempting to incorporate PDF.js into my website, but I'm struggling to do it correctly. When I try to display the PDF file on the screen, I encounter this issue: https://i.sstatic.net/aixrP.png Although I can't see the PDF file ...

Transform a file object into a regular object within React

I regret to inform you that I must post an image in order to better illustrate my issue. Currently, I am using the antd upload component for file uploads. After uploading files individually in multi-upload mode, the resulting image showcases my problem. ...

Properly maintaining child processes created with child_process.spawn() in node.js

Check out this example code: #!/usr/bin/env node "use strict"; var child_process = require('child_process'); var x = child_process.spawn('sleep', [100],); throw new Error("failure"); This code spawns a child process and immediately ...

The custom stylesheet added to index.html is not taking precedence over the Bootstrap 5 styles applied through NPM

In my Vue 2 project, I encountered an issue with Bootstrap 5.3 when installed via NPM. My custom CSS stylesheet in the index.html file was not able to override Bootstrap's CSS. Interestingly, I faced no problems when using Bootstrap from a CDN. Addit ...

What is the reason behind the failure of the cancel test?

I've created two test cases; one for testing the functionality of the Download button and the other for the Cancel button. However, I am encountering issues with the Cancel test failing consistently. Below is the code snippet where I'm attemptin ...

Comparing the use of jQuery's data() method versus directly accessing attributes with native JavaScript using get

I want to retrieve general information from my website using javascript. I have a few different options available: I could use an html element: <input type="hidden" value="MyValue"/> Another option is to use a custom attribute in an existing h ...

Tips for transforming promise function into rxjs Observables in Angular 10

As a beginner in typescript and angular, I am trying to understand observables. My query is related to a method that fetches the favicon of a given URL. How can I modify this method to use observables instead of promises? getFavIcon(url: string): Observ ...

Placing a point on a measurement scale according to a changing factor

I am completely new to html, css, and javascript. My goal is to create a color gradient bar and then place a dot on it based on a variable. I tried to implement a solution I found from various sources, but it is not functioning as expected, and I am seekin ...

Switching from PHP to JavaScript before returning to PHP to establish and manage sessions

Currently, I am in the process of resolving an issue I am facing. The problem arises when utilizing the following code for someone trying to sign into the admin panel: <script> function myFunction() { //alert('you can type now, end ...

How does [name] compare to [attr.name]?

Question regarding the [attr.name] and [name], I am utilizing querySelectorAll in my Typescript as shown below: this._document.querySelectorAll("input[name='checkModel-']") However, when I define it in the HTML like this: <input [name]="check ...

When the FLASK button is triggered, retrieve data from the FLASK and display it

This is a unique test where I will create a button to retrieve information from a MySQL database. However, it's important to first understand this concept. So here is my custom text within the Flask framework: @app.route('/pythonlogin/home', ...

Utilizing HTML5 history instead of hash URLs to preserve the user's browsing history

Our application is a single page that dynamically loads results based on query strings. The query string format we use is as follows: ?city=Delhi&pn=1 Within the SPA, there are different sections displayed on the same page. As users navigate through ...

What is the most effective method for testing event emitters?

Imagine I have a basic component structured like this: @Component({ selector: 'my-test', template: '<div></div>' }) export class test { @Output selected: EventEmitter<string> = new EventEmitter<string>() ...

Utilizing v-model dynamically to showcase the outcomes of a specific property within a v-for iteration

As I iterate over an array using v-for, the number of items in this array varies each time. Currently, I am able to input values into the fields and have them correctly update the data property associated with them. However, there are two issues that need ...

What is the best way to resize an image to fit its surroundings within a nested box?

Have you ever heard of a website called SPAM? It has a unique homepage that I want to replicate using JavaScript, jQuery, and some CSS. My main challenge is figuring out how to adjust the image size to match the center box on the page. I want to create th ...