iOS 7 iPad Safari Landscape innerHeight / outerHeight布局问题

时间:2013-09-25 18:07:34

标签: css ipad safari ios7

我们发现iOS 7中Safari的高度为100%的Web应用程序存在问题。似乎window.innerHeight(672px)与window.outerHeight(692px)不匹配,但仅限于横向模式。最终发生的事情是,在身体高度为100%的应用程序中,您可以获得20px的额外空间。这意味着当用户在我们的应用上滑动时,导航元素会被拉到浏览器镶边后面。这也意味着位于屏幕底部的任何绝对定位的元素最终都会关闭20px。

此问题在此处也列出了此问题: IOS 7 - css - html height - 100% = 692px

可以在这个模糊的截图中看到: iOS 7 Safari outerHeight issue

我们要做的就是解决这个问题,以便在Apple修复错误之前,我们不必担心它。

这样做的一种方法是绝对只在iOS 7中定位主体,但这相当于将额外的20px放在页面顶部而不是底部:

body {
    position: absolute;
    bottom: 0;
    height: 672px !important;
}

任何有关强制outerHeight与innerHeight匹配的帮助,或者对其进行黑客攻击以便我们的用户无法看到此问题的任何帮助都将非常感激。

13 个答案:

答案 0 :(得分:60)

就我而言,解决方案是将定位更改为固定:

@media (orientation:landscape) {
    html.ipad.ios7 > body {
        position: fixed;
        bottom: 0;
        width:100%;
        height: 672px !important;
    }
}

我还使用脚本来检测iOS 7的iPad:

if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i)) {
    $('html').addClass('ipad ios7');
}

答案 1 :(得分:16)

简单,清晰的CSS-Only解决方案:

html {
     height: 100%;
     position: fixed;
     width: 100%;
   }

iOS 7似乎正确设置了这个高度。此外,无需调整javascript事件等。 由于您正在使用全高度应用程序,如果它始终位置固定并不重要。

答案 2 :(得分:14)

Samuel的回答,正如Terry Thorsen所说,工作得很好,但如果网页已被添加到iOS家庭中,则会失败。

更直观的解决方法是检查window.navigator.standalone var。

if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && !window.navigator.standalone) {
    $('html').addClass('ipad ios7');
}

这种方式仅适用于在Safari内部打开,而不适用于在家中启动。

答案 3 :(得分:2)

Samuel的答案是最好的,但如果用户将页面添加到他们的主屏幕(主屏幕页面没有显示错误),它会中断。在添加类之前检查innerHeight:

if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i)) {
    if(window.innerHeight==672){
        $('html').addClass('ipad ios7');
    }
}

请注意,该错误也不会在webview下显示。

答案 4 :(得分:2)

我使用这个JavaScript解决方案来解决这个问题:

    if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && window.innerHeight != document.documentElement.clientHeight) {
  var fixViewportHeight = function() {
    document.documentElement.style.height = window.innerHeight + "px";
    if (document.body.scrollTop !== 0) {
      window.scrollTo(0, 0);
    }
  }.bind(this);

  window.addEventListener("scroll", fixViewportHeight, false);
  window.addEventListener("orientationchange", fixViewportHeight, false);
  fixViewportHeight();

  document.body.style.webkitTransform = "translate3d(0,0,0)";
}

答案 5 :(得分:1)

Samuel的方法的一个变种,但有位置:-webkit-sticky set on html对我来说是最好的。

@media (orientation:landscape) {
    html.ipad.ios7 {
        position: -webkit-sticky;
        top: 0;
        width: 100%;
        height: 672px !important;
    }
}

注意'top:0',而不是'bottom:0',目标元素是'html',而不是'body'

答案 6 :(得分:0)

基本上有两个错误 - 横向模式下窗口的高度以及用户从纵向模式重新加载时的滚动位置。我们用这种方式解决了这个问题:

窗口的高度由以下方式控制:

// window.innerHeight is not supported by IE
var winH = window.innerHeight ? window.innerHeight : $(window).height();

// set the hight of you app
$('#yourAppID').css('height', winH);

// scroll to top
window.scrollTo(0,0);

现在,上面的内容可以放入函数中并绑定到窗口调整大小和/或方向更改事件。就是这样......看例子:

http://www.ajax-zoom.com/examples/example22.php

答案 7 :(得分:0)

您需要JavaScript来解决此错误。 window.innerHeight具有正确的高度。这是我能想到的最简单的解决方案:

$(function() {
    function fixHeightOnIOS7() {
        var fixedHeight = Math.min(
            $(window).height(), // This is smaller on Desktop
            window.innerHeight || Infinity // This is smaller on iOS7
        );
        $('body').height(fixedHeight);
    }

    $(window).on('resize orientationchange', fixHeightOnIOS7);
    fixHeightOnIOS7();
});

您还需要在position: fixed上设置<body>

这是一个完整的,有效的例子:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <meta name="apple-mobile-web-app-capable" content="yes"/>
        <title>iOS7 height bug fix</title>
        <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
        <script>
            $(function() {
                function fixHeightOnIOS7() {
                    var fixedHeight = Math.min(
                        $(window).height(),
                        window.innerHeight || Infinity
                    );
                    $('body').height(fixedHeight);
                }

                $(window).on('resize orientationchange', fixHeightOnIOS7);
                fixHeightOnIOS7();

                // Generate content
                var contentHTML = $('#content').html();
                for (var i = 0; i < 8; i++) contentHTML += contentHTML;
                $('#content').html(contentHTML);
            });
        </script>
        <style>
            html,
            body
            {
                margin: 0;
                padding: 0;
                height: 100%;
                width: 100%;
                overflow: auto;
                position: fixed;
            }
            #page-wrapper
            {
                height: 100%;
                position: relative;
                background: #aaa;
            }
            #header,
            #footer
            {
                position: absolute;
                width: 100%;
                height: 30px;
                background-color: #666;
                color: #fff;
            }
            #footer
            {
                bottom: 0;
            }
            #content
            {
                position: absolute;
                width: 100%;
                top: 30px;
                bottom: 30px;
                overflow: auto;
                -webkit-overflow-scrolling: touch;
            }
        </style>
    </head>
    <body>
        <div id="page-wrapper">
            <div id="header">Header</div>
            <div id="content">
                <p>Lorem ipsum dolor sit amet.</p>
            </div>
            <div id="footer">Footer</div>
        </div>
    </body>
</html>

答案 8 :(得分:0)

参考接受的答案,我也对以下规则感到满意:

html.ipad.ios7 {
    position: fixed;
    width: 100%;
    height: 100%;
}

这有一个额外的好处,它似乎停止html元素滚动&#34;&#34;一个固定的身体元素。

答案 9 :(得分:0)

如果我使用它:

if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && !window.navigator.standalone) {
    $('html').addClass('ipad ios7');
}

我在Mac上的Safari显示相同的html类......所以它无法正常工作。

我试图结合一些东西 - 这对我有用,所以我可以在浏览器中管理它而没有浏览器视图。

<强>的jQuery

if (navigator.userAgent.match(/iPad/i) && (window.orientation) ){
     $('html').addClass('ipad ');
        if (window.innerHeight !=  window.outerHeight ){
          $('html').addClass('browser  landscape');              
    }
    else{
         $('html').addClass('browser portrait');                   
    }
} 

<强> CSS

@media (orientation:landscape) {
   html.ipad.browser > body {
       position: fixed;  
       height: 671px !important;
   }
}

/////使用此功能,您可以更灵活或使用其他操作系统和浏览器

答案 10 :(得分:0)

我遇到了同样问题的这个页面。 这里有很多有用的答案,有些则不是(对我来说)。

但是,我找到了一个解决方案,它适用于我的情况,并且完全独立于哪个操作系统版本以及现在或过去或将来的错误。

解释:开发一个Web应用程序(没有本机应用程序),其中包含几个固定大小的模块,全屏,类名为“module”

.module {position:absolute; top:0; right:0; bottom:0; left:0;}

其中包含一个类名为“footer”的页脚

.module > .footer {position:absolute; right:0; bottom:0; left:0; height:90px;}

没关系,如果我稍后将页脚的高度设置为另一个高度,或者甚至其高度是由其内容设置的,我可以使用以下代码进行更正:

function res_mod(){
    $('.module').css('bottom', 0); // <-- need to be reset before calculation
    var h = $('.module > .footer').height();
    var w = window.innerHeight;
    var o = $('.module > .footer').offset();
    var d = Math.floor(( w - o.top - h )*( -1 ));
    $('.module').css('bottom',d+'px'); // <--- this makes the correction
}

$(window).on('resize orientationchange', res_mod);

$(document).ready(function(){
    res_mod();
});

由于Matteo Spinelli的技能,我仍然可以毫无问题地使用iScroll,因为它的改变事件幸运地被解雇了。如果没有,则需要在更正后再次调用iScroll-init。

希望这有助于某人

答案 11 :(得分:0)

当收藏栏显示时,接受的答案无法应对。这是一个改进的赶上所有修复:

@media (orientation:landscape) {
  html.ipad.ios7 > body {
    position: fixed;
    height: calc(100vh - 20px);
    width:100%;
  }
}

答案 12 :(得分:-1)

如果你尝试

怎么办?
html{ bottom: 0;padding:0;margin:0}body {
position: absolute;
bottom: 0;
height: 672px !important;
}