Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make the scroll event bubbling on a fixed positionned element

I have HTML elements with a position: fixed within an second element with an overflow-y :auto

When the mouse is over the fixed element the scroll doesn't bubble to it's parent. When moving away, the scroll occurs.

I've reduced the situation to the code below

main {
  /* I am the element that scrolls */
  height: 200px;
  display: flex;
  flex-flow: row nowrap;
  overflow-y: auto;
}

main section {
  flex: 1 1 800px;
  max-width: 800px;
}

main nav {
  flex: 1 1 auto;
  min-width: 100px;
}

main nav a {
  /* I am the element that prevent scroll on when hovering */
  position: fixed;
}
<main>
  <aside>
    <nav>
      <a href="#">left</a>
    </nav>
  </aside>
  <section>
    <p>Could be a long text...</p>
  </section>
  <aside>
    <nav>
      <a href="#">right</a>
    </nav>
  </aside>
</main>

You can test it at JSBin by trying to scroll over the pink element or somewhere else.

Is there a way in CSS or even in JavaScript ?

like image 937
krampstudio Avatar asked Jun 11 '18 16:06

krampstudio


2 Answers

Seems Straight forward, position:fixed and/or position:absolute as you may now takes the element out of the document flow as if it doesn't exists, like it's somewhat just there for visual effects.

position:absolute still can bubble the scroll events of it's relative positioned ancestor as we know.

.parent {
  height: 100px;
  width: 100px;
  border: 1px solid;
  overflow-y: auto;
  /* Take this out to see the effect */
  position: relative;
}

p {
  height: 5000px;
  /* Mimic overflow */
}

.kid {
  height: 20px;
  width: 20px;
  border: 1px solid;
  position: absolute;
}
<div class="parent">
  <div class="kid"></div>
  <p></p>
</div>

However position:fixed is special, because it's relative to the browser window (viewport), it'll bubble the scroll event of the browser.

body {
  /* Mimic body has scrollbars */
  height: 5000px;
}

.parent {
  height: 100px;
  width: 100px;
  border: 1px solid;
  overflow-y: auto;
  /* Take this out to see the effect */
  position: relative;
}

p {
  /* Mimic overflow */
  height: 5000px;
}

.kid {
  height: 20px;
  width: 20px;
  border: 1px solid;
  position: fixed;
}
<div class="parent">
  <div class="kid"></div>
  <p></p>
</div>

Basically you can't make a fixed position element bubble up it's parent scroll event.

like image 151
Nothing Mattress Avatar answered Nov 03 '22 19:11

Nothing Mattress


Using JavaScript you can still handle the wheel event and trigger it to the parent element:

const fixedElts = document.querySelectorAll('nav a');
const parentElt = document.querySelectorAll('main');
const bubbleFixedScroll = e => {
    if(e.deltaMode){
       parentElt.scrollTop += e.deltaY;
    }
};
fixedElts.forEach( fixedElt => {
  fixedElt.addEventListener('wheel', bubbleFixedScroll) 
});

Of course the delta value can be adapted for a smother scrolling. Also some throttling can be added to prevent to much handlers to be executed.

like image 27
krampstudio Avatar answered Nov 03 '22 19:11

krampstudio