How to access the real 100vh on iOS in CSS
Set a root CSS var like so in your stylesheet:
// CSS vars
:root {
--real100vh: 100vh;
}
Then in JavaScript, on load (or jQuery ready event) and on also on resize, you want to run this code:
set100vhVar() {
// If less than most tablets, set CSS var to window height.
let value = "100vh"
// If window size is iPad or smaller, then use JS to set screen height.
if (window.innerWidth && window.innerWidth <= 1024) {
value = `${window.innerHeight}px`
}
document.documentElement.style.setProperty("--real100vh", value)
}
Now you can simply use the CSS: height: var(--real100vh);
wherever you want 100vh
to actually be the real 100vh
on mobile, and this will simply work!
It looks better if you also add a transition: height 0.4s ease-in-out;
on the same element, so it doesn't snap when you scroll down on mobile.
The advantage of using a CSS var to do this is that you can override this whenever you like, for example you might want certain breakpoints to be height: 500px
, and this is hard to do if you use an inline style. You can also use this inside calc()
, like height: calc(var(real100vh) - 100px);
which is useful for fixed headers.
If you use Vue/Nuxt, take a look at how we have implemented that here.
CSS3 100vh not constant in mobile browser
Unfortunately this is intentional…
This is a well know issue (at least in safari mobile), which is intentional, as it prevents other problems. Benjamin Poulain replied to a webkit bug:
This is completely intentional. It took quite a bit of work on our part to achieve this effect. :)
The base problem is this: the visible area changes dynamically as you scroll. If we update the CSS viewport height accordingly, we need to update the layout during the scroll. Not only that looks like shit, but doing that at 60 FPS is practically impossible in most pages (60 FPS is the baseline framerate on iOS).
It is hard to show you the “looks like shit” part, but imagine as you scroll, the contents moves and what you want on screen is continuously shifting.
Dynamically updating the height was not working, we had a few choices: drop viewport units on iOS, match the document size like before iOS 8, use the small view size, use the large view size.
From the data we had, using the larger view size was the best compromise. Most website using viewport units were looking great most of the time.
Nicolas Hoizey has researched this quite a bit: https://nicolas-hoizey.com/2015/02/viewport-height-is-taller-than-the-visible-part-of-the-document-in-some-mobile-browsers.html
No fix planned
At this point, there is not much you can do except refrain from using viewport height on mobile devices. Chrome changed to this as well in 2016:
- https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/BK0oHURgmJ4
- https://developers.google.com/web/updates/2016/12/url-bar-resizing
CSS 100vh is too tall on mobile due to browser UI
Usually the 100vh
height will account for the adjusted height, with is why you'll sometimes see mobile pages go funky when the browser's address bar slides down.
For browsers that don't account for the sliding bar within the vh
unit: The height for the address bars will not be constant across the browsers, so I'd advise against appending -50px
.
Try setting the height of the page (using javascript) with the window.innerheight
property.
function resetHeight(){
// reset the body height to that of the inner browser
document.body.style.height = window.innerHeight + "px";
}
// reset the height whenever the window's resized
window.addEventListener("resize", resetHeight);
// called to initially set the height.
resetHeight();
iOS Glitch: gap/space above 100vh body
Debugged this for quite some time, and finally found a fix.
Add the following code to your css. My guess is that the repaint adjusts the layout correctly. If the translateY doesn't work for you, try another way to trigger a repaint.
/* ------------------------------
iOS FIX: gap/space above body element on first load
-------------------------------- */
@media (max-width: 450px) {
@supports (display: grid) {
body {
animation: pageReflow 0.1s;
}
}
}
@keyframes pageReflow {
from {
transform: translateY(1px);
}
to {
transform: translateY(0px);
}
}
Related Topics
How to Consecutively Present Two Alert Views Using Swiftui
How to Display Nested Array Data Inside Uitableview Properly with Multiple Level of Sections
Selector to Get Indexpath Uicollectionview Swift 3.0
How to Create Otp Verification Screen and Detect Delete Backward on Multiple Uitextfield Is Swift
Swift: Unrecognized Selector Sent to Instance
iOS Calendar Access Permission Dialog, Force It to Appear
Uiimagepickercontroller Crashes App | Swift3, Xcode8
The Advertisingidentifier and Identifierforvendor Return "00000000-0000-0000-0000-000000000000"
Set Image and Title for Bar Button Item
Firebase Fcm Silent Push Notifications for iOS
Adding Convenience Initializers in Swift Subclass
Uibutton Does Not Work When It in Uiscrollview
How to Display Clickable Links in Uitextview
Uitextview Link Detection in iOS 7
Swiftui Withanimation Completion Callback
Warning: Uicollectionviewflowlayout Has Cached Frame Mismatch for Index Path 'Abc'