4

I've seen lots of questions/answers regarding detecting if an HTML element is scrollable (e.g. Detect scrollbar dynamically ). I need something similar, but not quite the same.

I have a div set to overflow-y: scroll;. On a desktop browser it shows the vertical scrollbar; that's fine. On an iPad, there is no vertical scrollbar; but you can scroll it by touch. The problem I'm having is that it's not always visually obvious on an iPad that the div can be scrolled. The Div simply contains a list; and sometimes my users think they're seeing the entire list and don't realize there's more if they scroll.

I'm thinking that if I can somehow detect if there is a visible scrollbar -- not simply if it's scrollable or not -- I can add a background image or similar visual cue for the mobile users who don't have the scrollbar. But I don't want a redundant cue if there's already a scrollbar.

I'm open either to JavaScript/PHP solutions to detect the scrollbar, or other ways (CSS?) to "cue" the fact that a section can be scrolled. Any ideas?

Stephen R
  • 3,512
  • 1
  • 28
  • 45
  • You can give [this](https://hasin.me/2013/08/17/detecting-if-a-dom-element-has-scrollbar/) a try, but I haven't tested it yet myself. – JakAttk123 Mar 15 '18 at 17:14
  • 1
    https://stackoverflow.com/questions/16670931/hide-scroll-bar-but-while-still-being-able-to-scroll this SO answer suggests that `Element.offsetWidth - Element.clientWidth` will return the dimensions of a scroll bar (will return 0 if none is present) – Doug Mar 15 '18 at 17:23
  • I don't get why people are voting to close this question. It hasn't really been asked before, and has very useful info in the responses and comments – Stephen R Mar 15 '18 at 19:34
  • Does this answer your question? [How can I check if a scrollbar is visible?](https://stackoverflow.com/questions/4814398/how-can-i-check-if-a-scrollbar-is-visible) – MartinNajemi Jul 28 '20 at 18:05

2 Answers2

3

JS solution: Compare the height (offsetHeight or clientHeight) of the element wrapping the content and the list itself -- then execute code accordingly.

If you want to detect a scrollbar, this stackoverflow answer may help: Hide scroll bar, but while still being able to scroll

Where you can do Element.offsetWidth - Element.clientWidth to get a scrollbar's width (it should return 0 if there is no scrollbar).

This Stack Overflow answer goes into detail about offset vs. client: What is offsetHeight, clientHeight, scrollHeight?

const listWrapper = document.getElementById('list-wrapper'),
      container   = document.getElementById('container'),
      list        = document.getElementById('list');

// compare the height of the target element ( listWrapper or list )
// against the element containing the element ( container )
if( list.offsetHeight > container.offsetHeight ){
  // if the list is longer, add a class to the containing element
  container.className = 'overflowed';
}

console.log( container.offsetHeight - container.clientHeight );
console.log( listWrapper.offsetHeight - listWrapper.clientHeight );
#container{ height: 150px; width: 150px; overflow-y: scroll; border: solid 1px red; }
#container.overflowed{
  background: linear-gradient(transparent 85%, rgba(0,0,0,0.25) );
}
<div id="container">
  <div id="list-wrapper">
    <ul id="list">
      <li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li><li>abcde</li>
    </ul>
  </div>
</div>
Doug
  • 1,435
  • 1
  • 12
  • 26
  • 1
    I don't think this is what he was trying to accomplish. This will allow you to use different styling if the element is overflowed, but he is trying to detect if the user's browser is hiding the scrollbar. – JakAttk123 Mar 15 '18 at 17:18
  • hmm ... yeah, this'll just give a visual cue if the content overflows. knowing if there is or is not a scroll bar visible really comes down to browser + device specs. To my knowledge, that's just research -- not something that can be coded to predict. – Doug Mar 15 '18 at 17:20
  • This tells me if it's scrollable, but not if the particular client (browser) actually displays a scrollbar. – Stephen R Mar 15 '18 at 17:26
  • 1
    Unfortunately, i think it may come down to research -- I get the dimensions of an existing scrollbar in chrome + mac -- but none is readily visible. At worst, if you go the style route regardless, it'll be an additional visual cue instead of risking no visual cues. – Doug Mar 15 '18 at 17:29
0

Based on Doug's hint about comparing offsetWidths, here's a working solution I came up with. Elements with the vscroll class are styled overflow-y: scroll;.

$(document).ready(function () {
    var scrollables = document.getElementsByClassName('vscroll');
    if( scrollables.length && 0 === scrollables[0].offsetWidth - scrollables[0].clientWidth ) {
        for ( const scrollable of scrollables ) {
            scrollable.style.background = 'url("/images/updnarrows_75.png") no-repeat 60% 50%';
        }
    }
});

The image is a set of faded up/down arrows that appear centered in the background of the div.

Stephen R
  • 3,512
  • 1
  • 28
  • 45