Closed dannybeckett closed 7 months ago
Good day @dannybeckett
Unfortunately this is a limitation of Safari. Technically the scrollbars are hidden (thats why the scrollbars are not visible in the inner square box), but the "viewport indicators" which are also shown when you just zoom in into the page are not. This also affected chrome and other browsers on mobile until they supported the scrollbar-width
css property. Safari doesn't support the css property even in version 17. (https://caniuse.com/?search=scrollbar-width)
The workaround here is to cancel the initialization of the plugin in this case:
OverlayScrollbars({
target: document.body,
cancel: {
nativeScrollbarsOverlaid: true,
},
});
Ah I see @KingSora
If I cancel the init then the custom scrollbars won't show, right?
In which case it's probably still preferable to keep it showing both native scrollbars + custom scrollbars, since Safari hides the native scrollbar except on scroll (thus making it unclear that there is more content beneath).
@dannybeckett If you cancel the initialization the custom scrollbars won't show and all related attributes like data-overlayscrollbars-initialize
are removed in case they are applied
Thanks for your help @KingSora - I'll leave it alone; hopefully Apple might eventually add support - one can hope xD
We all hope :D
Just to state the obvious, wrapping the contents of <body>
in a container <div>
is another workaround:
<html>
<body>
<div class="body-content" data-overlayscrollbars-initialize>
<div id="something">Your actual content here</div>
<div id="another">Continued...</div>
</div>
</body>
</html>
Also set it to use .body-content
rather than body
in:
const scrollbar_content = OverlayScrollbars(document.querySelector('.body-content'), {});
For me I also needed the following styles:
div.body-content {
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
Now the <body>
has a scrollbar without iOS' native scrollbars overlapping :)
@dannybeckett THanks for this suggestion!
Thats also a valid workaround but has other drawbacks to be aware of:
window.scrollTo
and other scroll apis related to the window
global@dannybeckett Thanks for this suggestion!
Thats also a valid workaround but has other drawbacks to be aware of:
- on mobile this will prevent the url bar to hide / show depending on your scrolling
- on mobile pull to refresh will not work anymore
- will alter the functionality of
window.scrollTo
and other scroll apis related to thewindow
global
I have just tested on Safari for iPhone and thankfully I'm not seeing any issues on our site.
The URL bar does fail to hide/show like you mentioned, but pull-to-refresh still works and our #anchor links still jump to the correct section.
We aren't using window.scrollTo
in our JS but we are using document.getElementById('someId').scrollIntoView()
(in seperate code to the anchor links) and it doesn't seem to affect that.
I'm very happy to have found a nice workaround, thank you so much for creating such an awesome piece of kit!
@KingSora So after posting that, I've spent several hours working out the fix for a "gotcha" that I've found when using my workaround above. On Chrome for Windows the arrow up/down keyboard keys do not work unless you click somewhere in the middle of the page first. On an iPad with an Apple Magic Keyboard attached, no amount of clicking the middle of the page will enable the up/down arrow keyboard keys.
I was able to workaround this by changing the stylesheet to:
html, body, div.body-content {
height: 100%;
width: 100%;
}
(Removing position: absolute;
as well as left: 0; top: 0;
and also applying the sizes to html
and body
)
Then adding tabindex="-1"
to a div within .body-content
but not on .body-content
itself (tabindex
denotes that this element is focusable, and -1
denotes that it can only be focused on programmatically and not by the user).
Then focus this inner <div>
on page load & when the scrollbar is clicked:
function refocus() {
document.getElementsByClassName('some-inner-div')[0].focus();
}
window.addEventListener('load', function() {
refocus();
var classNames = ['os-scrollbar-track', 'os-scrollbar-handle'];
for(var i = 0; i < classNames.length; i++) {
var elements = document.getElementsByClassName(classNames[i]);
for(var j = 0; j < elements.length; j++) {
document.getElementsByClassName(classNames[i])[j].addEventListener('mouseup', refocus);
}
}
});
This fixes the up/down arrow keys on both Chrome for Windows + Safari for iPad, but leaves a black border around the div on Windows - which you can remove with:
div.some-inner-div:focus {
outline: none;
}
The last thing that needs to be done is to set data-overlayscrollbars-initialize
on html
+ body
+ div.body-content
to remove the flickering of the OS-native scrollbars.
@dannybeckett I didn't mention it before because I thought you didn't have any issues, but OverlayScrollbars is able to do the initialization you did out of the box (with all the focus management etc.):
OverlayScrollbars({
target: document.body,
elements: {
viewport: false,
},
cancel: {
body: false,
},
});
@KingSora Sorry to bother you again! I tried your code above on my site (after undoing the things I did before, I.E. adding the container <div>
, JS focus + CSS).
The custom scrollbars are visible, and the iOS-native scrollbars no longer overlap, but unfortunately it isn't focusing.
On Chrome for Windows: I have to click somewhere in the middle of the page to get the arrow up/down keyboard keys to work.
On Safari for iPad with a physical keyboard attached: interestingly I don't have to tap the screen, but I can only press the arrow down key once. After that you are unable to press either the up or down arrow keys. However scrolling by touch dragging the middle of the screen immediately works after.
On the other hand, if you don't press the arrow down key on the iPad first, then trying to touch-drag the middle of the page to scroll it fails for about the first 5 attempts. The page does not scroll.
Am I able to specify which element should receive focus? In my example that would be div.some-inner-div
, which is a few levels deep within <body>
.
Any ideas please? I will admit I am not 100% sure what the target
, viewport
and cancel body
commands together are doing exactly. Sorry for being a pain!
Thanks a lot!
@dannybeckett OverlayScrollbars will automatically focus its viewport element, not your custom element... can you please post an small example on StackBlitz with your setup? I then can take a look what could be done
@dannybeckett I've just published v2.7.1
which includes fixes to your issue... please try it out and give feedback :)
Wow @KingSora I am incredibly impressed with the speed of your response - thank you for being so dedicated!
Needless to say that 2.7.1 is perfect in every way, it has truly hit the nail right on the head! No more of my yucky workarounds! 🥳😆
Seriously, great job! Thank you so much once again!!
All the best
@dannybeckett glad I could help you :)
Describe the bug On a physical iPhone, iOS's native scrollbar is visible when scrolling the page. This bug also affects the demo page.
To Reproduce
Expected behavior Native scrollbars should not be visible
Examples Demo page
Environment
Additional context
Related https://github.com/KingSora/OverlayScrollbars/issues/545