CSS3 100vh not constant in mobile browser

I have a very odd issue... in every browser and mobile version I encountered this behavior:

  • all the browser have a top menu when you load the page (showing the address bar for example) which slide up when you start scroll the page.
  • 100vh are calculated only on visible part of viewport, so when the browser bar slide up 100vh increases (in terms of pixels)
  • all layout re-paint and re-adjust since the dimensions have changed
  • bad jumpy effect for user experience
  • how can avoid this problem? When I first heard of viewport-height I was excited and I thought I could use it for fixed height blocks istead of using javascript, but now I think the only way to do that is in fact javascript with some resize event...

    you can see the problem at: sample site

    Can anyone help me with / suggest a CSS solution?


    simple test code:

    /* maybe i can track the issue whe it occours... */
    $(function(){
      var resized = -1;
      $(window).resize(function(){
        $('#currenth').val( $('.vhbox').eq(1).height() );
        if (++resized) $('#currenth').css('background:#00c');
      })
      .resize();
    })
    *{ margin:0; padding:0; }
    
    /*
      this is the box which sould keep constant the height...
      min-height to allow content to be taller than viewport if too much text
    */
    .vhbox{
      min-height:100vh;
      position:relative;
    }
    
    .vhbox .t{
      display:table;
      position:relative;
      width:100%;
      height:100vh;
    }
    
    .vhbox .c{
      height:100%;
      display:table-cell;
      vertical-align:middle;
      text-align:center;
    }
    <div class="vhbox" style="background-color:#c00">
      <div class="t"><div class="c">
      this div height should be 100% of viewport and keep this height when scrolling page
        <br>
        <!-- this input highlight if resize event is fired -->
        <input type="text" id="currenth">
      </div></div>
    </div>
    
    <div class="vhbox" style="background-color:#0c0">
      <div class="t"><div class="c">
      this div height should be 100% of viewport and keep this height when scrolling page
      </div></div>
    </div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

    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. Mobile Chrome seems to want to adapt this too, although it is not sure if they will follow through.


    For many of the sites I build the client will ask for a 100vh banner and just as you have found, it results in a bad "jumpy" experience on mobile when you begin to scroll. This is how I solve the problem for a smooth consistent experience across all devices:

    I first set my banner element CSS to height:100vh

    Then I use jQuery to get the height in pixels of my banner element and apply an inline style using this height.

    var viewportHeight = $('.banner').outerHeight();
    $('.banner').css({ height: viewportHeight });
    

    Doing this solves the issue on mobile devices as when the page loads, the banner element is set to 100vh using CSS and then jQuery overrides this by putting inline CSS on my banner element which stops it from resizing when a user begins to scroll.

    However, on desktop if a user resizes their browser window my banner element won't resize because it now has a fixed height set in pixels due to the above jQuery. To address this I use Mobile Detect to add a 'mobile' class to the body of my document. And then I wrap the above jQuery in an if statement:

    if ($('body').hasClass('mobile')) {
      var viewportHeight = $('.banner').outerHeight();
      $('.banner').css({ height: viewportHeight });
    }
    

    As a result, if a user is on a mobile device the class 'mobile' is present on the body of my page and the above jQuery is executed. So my banner element will only get the inline CSS applied on mobile devices meanwhile on desktop the original 100vh CSS rule remains in place.


    I just found a web app i designed has this issue with iPhones and iPads, and found an article suggesting to solve it using media queries targeted at specific Apple devices.

    I don't know whether I can share the code from that article here, but the address is this: http://webdesignerwall.com/tutorials/css-fix-for-ios-vh-unit-bug

    Quiting the article: "just match the element height with the device height using media queries that targets the older versions of iPhone and iPad resolution."

    They added just 6 media queries to adapt full height elements, and it should work as it is fully CSS implemented.

    Edit pending: I'm unable to test it right now, but I will come back and report my results.

    链接地址: http://www.djcxy.com/p/15498.html

    上一篇: 使Iframe适合容器剩余高度的100%

    下一篇: 在移动浏览器中CSS3 100vh不是固定的