mouse-scrolling an element inside shadowRoot does not work in Chrome

237 Views Asked by At

I have a div inside a shadowRoot that has a fixed height and overflow set to auto. The content is larger than the box and therefor scrollbars appear. When the (outer) page already has scrollbars it seems that it does not scroll the div when using Chrome. Mouse-scrolling will only target the page even though hovering the div.

When doing this outside a shadowRoot the div hovered is being scrolled when using the mouse. And it seems this issue works in other browsers than chrome even when using a shadowRoot.

const App = () => {
  return (
    <div
      className="App"
      style={{ height: "100px", width: "500px", overflow: "auto" }}
    >
      <h1 style={{ height: "100px" }}>Try mouse-scrolling here</h1>
      <h2>Hidden!</h2>
    </div>
  );
}

const container = document.createElement("div");
const shadowRoot = container.attachShadow({ mode: "open" });
const domElement = document.getElementById("root");

domElement.append(container);
const root = ReactDOM.createRoot(shadowRoot);

root.render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div style="height: 1000px">
  <div id="root">Hello world</div>
</div>

In this example if setting element.style root element to overflow: hidden it the scrollbar starts to work in the div.

I have tried to set onMouseEnter={() => (document.body.style.overflow = 'hidden')} onMouseLeave={() => (document.body.style.overflow = 'auto')} on the App and that kind of solves the problem but it ends up with the page moving slightly. I also tried to add the scrollbar-gutter: stable; to remove this glitch when removing the outer scrollbar and it kind of works, but I would like to have a fix that does not have to change the webpage itself that much.

Is there a way to make the div handle mouse scrolling without these hacks?

(There is also a working example in codesandbox: https://codesandbox.io/s/scrollbar-issue-f5tgm4?file=/src/index.js)


Background info! Why do I want to do this? I am developing an app with micro frontends. We are also in the middle of replacing the design-system. So some of the micro-frontends that are embedded for different pages might bleed the incorrect version of the base CSS classes into the page.

In order to not bleeding CSS we are using webcomponents. But it seems that there some limitations to it as described above. One of the micro-frontends is the page navigation bar that contains a dropdown list. When deploying this application as a webcomponent I cannot mouse-scroll the navigation-bar in chrome.

I have drilled the problem down to this example which only describes the technical problem without the whole page-navigation logic.

2

There are 2 best solutions below

0
stalet On BEST ANSWER

It seems that some browser plugins might affect which scrollbars that is enabled. I had the Linux Scroll Speed Fix browser plugin installed and that changed the behaviour.

When removing this plugin from the browser it works like expected.

https://chrome.google.com/webstore/detail/linux-scroll-speed-fix/mlboohjioameadaedfjcpemcaangkkbp

1
Ivan_OFF On

I am answering you even if I didn't get the full reason behind this question at all, what are you trying to achieve?
Is this a question about shadow-root logic inside html?

You are appending the component inside the root div

 <div id="root">Hello world</div>

which means the completed HTML will look like this:

<div id="root">
    Hello world
    <div>
    #shadow-root
        <div class="App"
        style="height: 100px; width: 500px; overflow: 
        auto;">
     <h1 style="height: 100px;">
         Try mouse-scrolling here
     </h1> 
     <h2>
         Hidden!
     </h2>
    </div>
      #end-shadow-root
</div>
</div>

This case tell us that only the component is scrollable inside itself, the div containing hello world is not part of the shadow dom and is part of the bigger container root level which has a scrollbar too!
You get the scroll inside the component and also the scroll outside the component.

If I mistaken your question, I will be more than glad to help you reaching your goal.