5

I'm looking for a generic solution to find the scrollable container of an element (I'd like to listen to the scroll event). The normal approach would be to traverse up in the DOM tree in check the parent elements until one of them is scrollable - here are some solutions like this. However this will fail if shadow DOM is also in the picture.

Here's an example structure:

<app-home>
  <ion-content>
    #shadow-root
      <div class="inner-scroll">
        <slot>
          -> <my-element> (reveal)
        </slot>
      </div>
    <my-element>...</my-element>
  </ion-content>
</app-home>

In the above example the scrollable element is .inner-scroll, which is inside the shadow dom of ion-content. Since my-element gets into the container through the slot, traversing up the tree will never reach the scroll container (my-element -> ion-content -> app-home).

I found that ion-content has a getScrollElement method, which can be used in this specific case, however I'd like to know if there's a generic DOM based solution, since I'd like this to work regardless of the context.

UPDATE:

To be more clear, I'd like my-element to be a standalone, reusable component, which can find it's scrolling container, no matter where it's placed. What I found, that the built in scrollIntoView method works on the DOM element, and it scrolls the correct container, meaning that the browser somehow figures it out, but does not expose a method which returns the scroll container.

Another idea was to listen to the scroll event on a higher level, without knowing the exact element, but this is not working either, because the scroll event does not propagate.

Any ideas?

istvan.halmen
  • 3,320
  • 1
  • 23
  • 29
  • these answers might help https://stackoverflow.com/a/69958607/965666 https://stackoverflow.com/a/69959491/965666 – jimmont Nov 14 '21 at 01:18

2 Answers2

2

Get the <ion-content> element and use its shadowRoot element to query the scrollable element.

const ionContent = document.querySelector('app-home > ion-content')
const scrollable = ionContent.shadowRoot.querySelector('.inner-scroll')

Then you can use querySelector in your scrollable element to find the desired element. If there are more scrollable elements in the shadow DOM, you can use querySelectorAll to return an array of nodes.

herodrigues
  • 948
  • 1
  • 7
  • 11
  • 3
    Thanks, this is indeed a pure DOM API solution, however it's not generic in the sense that I still need to know about the DOM structure. I'd like `my-element` to be a standalone, reusable component, which can find it's scrolling container, no matter where it's placed. – istvan.halmen Feb 15 '19 at 07:37
0

It may be too late, but answering if it helps anyone else looking for an answer.

One possible solution is to use the getComputedStyle w.r.t the parent element and keep iterating upwards until you find a minimum of 2 combinations - height+width is longer than its own parent + it has overflow property (via getComputedStyle) set to anything that allows scroll.

Himadhar H
  • 106
  • 9