We have a simple mobile app running in Mobile Safari (MS) on iOS. When the user scrolls down the page n pixels, a "top" button slides up from the bottom. The top button is fixed position. Problem is, when you start scrolling in MS, the navigation and toolbar UI is hidden. When you tap the "top" button, it reveals the bottom toolbar and a second tap is required to tap the "top" button. Is there any way to disable the default "tap on the bottom part of the viewport to reveal the toolbar" behavior so our top button works as expected (i.e. jumps to the top of the page with one click, not two?
-
1There are ways to do this on a Jailbroken device. The author of the Safari Bar Lock tweak managed to swizzle the method which controls the toolbar. https://www.reddit.com/r/jailbreak/comments/1v6rfi/safari_bar_lock_tweak_to_make_safari_address_bar/ – JAL Dec 08 '15 at 14:44
6 Answers
No there is not. You can control the content of your webpage but not the behavior of the safari app.

- 55,990
- 32
- 132
- 223

- 5,807
- 6
- 38
- 83
-
8There should be a way to tell mobile safari not to do this, though. It's not so different than say, disabling autocorrect on a text input. – nnyby Mar 04 '14 at 16:19
-
1The two are different. Autocorrect is an option on how the app renders an element and in that case you can control a lot. You want to change the behavior of the UI of safari. I think what you are trying to do is the same as trying to change the icon of the reload button or the font of the address bar. – Mika Mar 04 '14 at 16:25
-
2controlling the behavior of the OS (what the user expect, not what your site wish to enforce) would be very bad practice – blld Dec 09 '15 at 01:56
The simple solution here is to add about 50px padding-bottom on your bottom most div. Safari seems to think that you are trying to access the bottom navigation bar, unless you click well above the bottom area. With extra padding at bottom, the user will click much higher on the page (not always, but in general).

- 821
- 9
- 14
-
3How would this not also change the visual appearance (by producing a gap below the div or increasing the div's height)? – 2540625 Mar 02 '20 at 02:34
-
Mika and typeoneerror are correct, but there is a workaround.
The best workaround solution I found (that doesn't require minimal-ui
) is to force the bottom navigation of iOS Safari to always stay open/visible. That way, clicks to the bottom of the window never open the bottom navigation since it's always open.
To do that, you just need to apply some CSS and browser targeting with JS. Detailed steps on how:
For iOS 7.1, you can set this in your header to minimize the UI:
<meta name="viewport" content="width=device-width, minimal-ui">
It was introduced in iOS 7.1 beta 2. This site was instrumental in helping me understand how minimal-ui works: http://www.mobilexweb.com/blog/ios-7-1-safari-minimal-ui-bugs

- 12,795
- 5
- 39
- 47
-
20Yeah but Apple removed minimual-ui in iOS 8 :( http://stackoverflow.com/questions/24889100/ios-8-removed-minimal-ui-viewport-property-are-there-other-soft-fullscreen – Styledev Oct 21 '14 at 06:22
Here's how I'm dealing with this. With a position:fixed;bottom:0
toolbar of my own, I'm adding 44px offset to it (with a semi-transparent buffer zone) shortly after the safari toolbar is hidden (as this is the scenario where a tap near the bottom will reveal the toolbar again).
var min_inner_height = false;
var max_inner_height = false;
var passiveIfSupported = false;
try {
window.addEventListener("test", null, Object.defineProperty({}, "passive", {
get: function () {
passiveIfSupported = {
passive: true
};
}
}));
} catch (err) {}
document.addEventListener('scroll', function (e) {
var win_inner_h = window.innerHeight;
if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
if (min_inner_height === false || win_inner_h < min_inner_height) {
min_inner_height = win_inner_h;
}
if ((max_inner_height === false || win_inner_h > max_inner_height) && win_inner_h > min_inner_height) {
max_inner_height = win_inner_h;
}
if (max_inner_height !== false && max_inner_height == win_inner_h) {
addElementClass(document.body, 'safari-toolbars-hidden');
} else {
removeElementClass(document.body, 'safari-toolbars-hidden');
}
}
}, passiveIfSupported);
This basically adds the .safari-toolbars-hidden
class to the <body>
sometime around when they disappear due to the user scrolling down the page.
At this point, I move my own toolbar up the page:
.my-bottom-toolbar {
bottom: 0px;
position: fixed;
}
@supports (-webkit-overflow-scrolling: touch) {
/* CSS specific to iOS devices */
.my-bottom-toolbar {
box-shadow: 0 44px 0 rgba(255, 255, 255, 0.8);
transition: bottom 0.15s ease-in-out;
}
.safari-toolbars-hidden .my-bottom-toolbar {
bottom: 44px;
}
}
Hope this helps someone!
Instead of offsetting by a further 44px, you could also add an extra 44px of bottom padding if that works better for your case.
-
How would this not also change the visual appearance (by producing a gap below the element or increasing the element's height)? – 2540625 Mar 02 '20 at 02:34
-
1Yes, it changes the appearance as in there's always 44px of space reserved for where the safari toolbar will appear. So I'm saving the user a tap, by getting them to aim above that blank area in the case where aiming below that would just reveal the toolbar. When the toolbar is there the extra space goes away. – EoghanM Mar 13 '20 at 21:25
-
Works great on iOS 14 ! Only thing is I would use " document.body.classList.add("safari-toolbars-hidden");" and .remove() instead of your custom method. Also, I'm wondering does Android/Chrome hide/show bottom bar and how to handle it ? – Aerodynamic Sep 10 '21 at 07:20
The best solution for me comes from this article.
My solution is with react but simply translated from the articles solution.
import { useWindowHeight } from '@react-hook/window-size/throttled';
//... inside your component
const height = useWindowHeight();
React.useEffect(() => {
const vh = height * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
}, [height]);
body {
/* other styles */
height: 100vh;
height: calc(var(--vh, 1vh) * 100);
}
Now when the innerHeight changes the hook is fired and the height variable is adjusted. The window's innerHeight changes when the safari url bar and bottom navigation are hidden so my app fits just right for both situations.

- 25,806
- 2
- 33
- 43