Chrome on iPhone overflows content on empty page (on new tab only, not reload)

1.6k views Asked by At

On IOS Chrome, the body overflows on a new tab or page with no content, but if the page is reloaded, the problem is fixed. It poses a problem for any element positioned at the bottom (absolute or fixed). Here is the code to reproduce the problem:

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width,minimum-scale=1, maximum-scale=2, initial-scale=1">
      <meta name="apple-mobile-web-app-capable" content="yes">
      <style>* {
         box-sizing: border-box;
         }
         html{
          height:100%;
         }
         body {
          height:100%;
          background-color:yellow;
          margin:0 0;
          border: 30px solid red;
         }
      </style>
   </head>
   <body></body>
</html>

The border should be shown all around the viewport but is being hidden behind the bottom Nav bar. Here is the result from the code above:

New page / tab on Mobile chrome

After page reload

Things I have tried (none of them worked):

I have tried for a week to find a workaround but to no avail. Any help would be greatly appreciated

Edit: My issue is different from HTML body not filling complete width on mobile devices as I don't have an issue with filling the body, I have an overflowing body issue and mobile chrome behaving differently on a new page as opposed to an existing page. The workarounds on the page didn't work for my issue

My question is the following: Can somebody find a way using css or JS for the HTML body to not overflow when a new page is opened using the code above?

4

There are 4 answers

1
coreuter On BEST ANSWER

I've reproduced your problem and might have found a solution. I've found this which I think causes your problem:

[...] The core issue is that mobile browsers (I’m looking at you, Chrome and Safari) have a “helpful” feature where the address bar is sometimes visible and sometimes hidden, changing the visible size of the viewport. Rather than adjusting the height of 100vh to be the visible portion of the screen as the viewport height changes, these browsers instead have 100vh set to the height of the browser with address the address bar hidden. The result is that the bottom portion of the screen will be cut off when the address bar is visible, thus defeating the purpose of 100vh to begin with.

The article suggests that

One way to get around this issue is to rely on javascript instead of css. When the page loads, setting the height to window.innerHeight will correctly set the height to the visible portion of the window. If the address bar is visible, then window.innerHeight will be the height of the full screen. If the address bar is hidden, then window.innerHeight will be the height of just the visible portion of the screen, as you’d expect.

In the comments they suggested to store the inner height in a CSS variable, refresh it every time the event resize or orientationchange is fired and apply it to the html and body tags. In my tests that worked only partially. Accessing the page from a link with target="_blank" worked fine, but refreshing or directly accessing the page would show the problem you described while accessing the page through a link. To fix that, I'm also updating the variable during the load event. On my iPhone 6s and the latest Chrome App accessing the page by link or directly seem to work fine now. I hope this is what you are looking for:

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,minimum-scale=1, maximum-scale=2, initial-scale=1">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <style>
      * {
        box-sizing: border-box;
      }

      html,
      body {
        height: 100%;
        height: 100vh;
        height: calc(var(--vh, 1vh) * 100);
      }

      body {
        background-color: yellow;
        margin: 0 0;
        border: 30px solid red;
      }
    </style>
  </head>

  <body></body>

  <script>
    function fixHeight() {
      document.documentElement.style.setProperty('--vh', `${window.innerHeight / 100}px`);
    };

    addEventListener('load', fixHeight);
    addEventListener('resize', fixHeight);
    addEventListener('orientationchange', fixHeight);
  </script>

</html>
4
Kyle Pollard On

WebKit handles 100% height a little strangely, you'll want to use a vendor prefixed property for WebKit devices:

body {
  min-height: 100vh;
  min-height: -webkit-fill-available;
}
html {
  height: -webkit-fill-available;
}

Source

1
KuldipKoradia On

This is the duplication for the same question things are problem will be same just asking method is different.

This is the same question previously asked and also details in right answer explained well.

CSS3 100vh not constant in mobile browser

This will help you to understand what is the problem you are facing.

0
Harry Fry On

A solution I found regarding absolute positioning - within Chrome on iOS it appears the window.innerHeight initialises with the fullscreen height, then switches to height between the address bar and bottom toolbar shortly after (approx 100ms or so). In my case was 667px and 553px respectively.

If you programatically pass the window.innerHeight into the height of the parent element of the app to make the height of the app the same as the inner height, as well as giving the top element position: relative;, all children of this element with the styling position: absolute; will have their position relative to this parent element, NOT the webpage.

It doesn't solve the issue of having the excess height below the content, but it solves the absolute positioning.

HTH.