Detect when window vertical scrollbar appears

Viewed 51119

Is there a simple and reliable solution for detecting window vertical scrollbar appears/disappears?

window.onresize isn't triggered when after JavaScript DOM manipulation page becomes high enough for appearing scrollbar.

In this very similar post Detect if a page has a vertical scrollbar described solution how to detect whether scrollbar is present or not, but I need to know when exactly it appears.

7 Answers

It's all about when you need to determine the scrollbar's visibility.

The OP speaks of a time "after JavaScript DOM manipulation". If that manipulation happens in your code, then that's the time for checking if the scrollbar is visible. Why do you need an event in addition to that? How is it that you don't know when this DOM manipulation occurs?

I realize this is an old question, but I'm just now dealing with this in a pure javascript project, and I have no issue knowing when to check for scrollbar visibility. Either a user event fires, or a system event fires, and I know when the DOM manipulation occurs because I'm causing it via javascript. I don't see a case where that javascript DOM manipulation is outside of my code's awareness.

Maybe a scrollbarVisibilityChange event would be convenient, but it's certainly not necessary. This strikes me as a non-issue, 9 years later. Am I missing something?

If you only need to detect the scroll appearance on Windows browsers (except IE), here's my solution with Resize Observer API for vertical scroll as an example.

Idea

  • Append <div> with position: fixed to <body>
  • Make it 100% width and observe for size changes
  • The appearance of the scroll reduces the <div>'s width, which in turn calls the observer callback.

Why only Windows browsers?

Mobile and macOS browsers have a disappearing scroll that is taken out of the document flow and doesn't affect the page layout.

Why should the position be fixed and not absolute?

Element with position: fixed is positioned relative to the initial containing block established by the viewport.

position: absolute may fail if the <body> is also absolutely positioned and has a different width than the viewport.

const innerWidthFiller = document.createElement('div')
innerWidthFiller.style.cssText = 'position: fixed; left: 0; right: 0'
document.body.appendChild(innerWidthFiller)

const detectScroll = () => {
  const {clientHeight, scrollHeight} = document.documentElement
  window.result.value = scrollHeight > clientHeight
}

const resizeObserver = new ResizeObserver(detectScroll)
resizeObserver.observe(innerWidthFiller)
#test {
  border: 1px solid;
  white-space: nowrap;
}

output {
  font-weight: bold;
}
<button onclick="test.style.fontSize='100vh'">Enlarge the text</button>
<button onclick="test.style.fontSize=''">Reset</button>
Page scroll state: <output id="result"></output>

<hr>

<span id="test">Test element</span>

Related