PhotoSwipe icon indicating copy to clipboard operation
PhotoSwipe copied to clipboard

Hiding the scrollbar

Open tomdav999 opened this issue 7 years ago • 5 comments

I found the vertical scrollbar to be distracting (and confusing) when viewing images. I'm sure there is a cleaner solution, but here is what I did to allow photoswipe to display on top of the scroll bars (effectively hiding them when viewing images). Photoswipe looks much better now!

Test page: http://www.nwhikers.net/test.htm (be sure to hit refresh)

Original code (decided to ditch this):

<body><div id="body_scroll"><div id="body_padding">
<script type="text/javascript">
var isFixedPosition = function() {
// would be best to use _isFixedPosition from photoswipe rather than re-create it here
}
if (isFixedPosition()) { // only do this if photoswipe will use position: fixed
    document.body.setAttribute("style", "overflow: hidden; margin: 0px");
    document.getElementById("body_scroll").setAttribute("style", "position: absolute; width: 100%; height: 100%; overflow: auto");
    document.getElementById("body_padding").style.padding = "8px"; // or set class
}
</script>
<!-- body content goes here -->
</div></div></body>

EDIT: revised code (based on comments below):

// add this in var _options = {
    _options.hideScroll: true,

// after this line in init: function() {
        var oldPhone = _features.isOldIOSPhone || _features.isOldAndroid || _features.isMobileOpera;
// add these lines:
        _features.hideScroll = (_options.hideScroll && !oldPhone && _options.modal && document.body.clientWidth);
        if (_features.hideScroll) {
            _features.restoreScroll = document.body.getAttribute('style');
            document.body.style.width = window.getComputedStyle(document.body).width;
            document.body.style.overflow = 'hidden';
        }

// add these lines:
        if (_features.hideScroll) {
            if (_features.restoreScroll) {
                document.body.setAttribute('style', _features.restoreScroll);
            } else {
                document.body.removeAttribute('style');
            }
        }
// before this line in close: function() {
        _showOrHide(self.currItem, null, true, self.destroy);

tomdav999 avatar Sep 24 '16 01:09 tomdav999

I'm aware of this issue and PhotoSwipe does not hide scrollbar on purpose.

Your technique is fine (even though it can potentially causes issues in older browsers that don't support overflow-y:scroll well), Google Photos uses a similar one, but I can not ship it "by default".

PhotoSwipe could remove scrollbar just by applying overflow:hidden & padding-right to html/body itself directly before it is opened. But it causes very complex relayout and paint (as a browser has to recalculate layout of the whole page), which will cause lag during the opening transition (especially if there is a lot of content on page).

would be best to use _isFixedPosition from photoswipe rather than re-create it

I'm planning to drop non-fixed position in the new version. If browser won't support it - new version will just open image in new tab.

dimsemenov avatar Sep 24 '16 06:09 dimsemenov

Thanks, just curious what issues this technique would cause in older browsers? Best case, wouldn't they just show the scrollbar? Worst case 2 scrollbars? Seems a small price to pay to get rid of the scrollbar for the vast majority of users.

I avoided padding-right for a couple reasons. First, as you said it causes relayout (whereas my solution does not). Also, I believe you need to guess at the scrollbar width.

tomdav999 avatar Sep 24 '16 08:09 tomdav999

Worst case - page won't scroll at all or won't have momentum scrolling. check https://github.com/filamentgroup/Overthrow#browser-support

Browser does a lot of things to optimize the performance of the main scroll, and even though scroll on inner element looks alike, it might behave slower or just differently. For example, if you load your page and try to scroll down with keyboard arrow keys - it won't work unless the overflow:scroll element is focused.

dimsemenov avatar Sep 24 '16 09:09 dimsemenov

Thanks for the feedback. I hadn't considered these side effects. I ended up ditching my original technique in favor or your first suggestion. I'm assuming that setting the body width before removing the scrollbar will minimize relayout.

tomdav999 avatar Sep 24 '16 11:09 tomdav999

I updated the code above to use getComputedStyle since it returns the decimal width. I was originally using clientWidth which had undesirable side effects due to it being a rounded width.

tomdav999 avatar Jan 14 '17 12:01 tomdav999