iOS 7 iPad Safari-Landschaft innerHeight / OuterHeight-Layoutproblem

72

Wir sehen Probleme mit einer Web-App, die unter Safari in iOS 7 eine Höhe von 100% hat. Es scheint, dass window.innerHeight (672px) nicht mit window.outerHeight (692px) übereinstimmt, sondern nur im Querformat. Was am Ende passiert, ist, dass Sie in einer App mit 100% Körpergröße 20 Pixel zusätzlichen Speicherplatz erhalten. Dies bedeutet, dass beim Navigieren eines Benutzers in unserer App die Navigationselemente hinter das Chrome des Browsers gezogen werden. Dies bedeutet auch, dass alle absolut positionierten Elemente, die sich am unteren Bildschirmrand befinden, 20 Pixel entfernt sind.

Dieses Problem wurde auch in dieser Frage hier umrissen: IOS 7 - CSS - HTML-Höhe - 100% = 692px

Und kann in diesem mehrdeutigen Screenshot gesehen werden: iOS 7 Safari OuterHeight Problem

Wir versuchen, dies zu umgehen, damit wir uns keine Sorgen machen müssen, bis Apple den Fehler behoben hat.

Eine Möglichkeit, dies zu tun, besteht darin, den Körper nur in iOS 7 absolut zu positionieren. Dadurch werden die zusätzlichen 20 Pixel jedoch ganz oben auf der Seite anstatt unten angezeigt:

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

Jede Hilfe beim Erzwingen, dass OuterHeight mit InnerHeight übereinstimmt, oder beim Hacken, damit unsere Benutzer dieses Problem nicht sehen können, wäre sehr dankbar.

hisnameisjimmy
quelle
2
Weitere Informationen finden Sie unter
Vikash Pandey
1
Nebenbei bemerkt: Dieser Fehler scheint unter iOS8 behoben zu sein. Problemumgehungen sollten nur auf iOS7 abzielen.
Patrick Rudolph

Antworten:

60

In meinem Fall bestand die Lösung darin, die Positionierung auf fest zu ändern:

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

Ich habe auch ein Skript verwendet, um das iPad mit iOS 7 zu erkennen:

if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i)) {
    $('html').addClass('ipad ios7');
}
Samuel Moreno López
quelle
5
Ich habe dies mit window.scrollTo(0,0);Orientierungsänderungen kombiniert und es scheint 99% unserer Probleme gelöst zu haben. Geben Sie mir ein paar Tage Zeit, um dies in der Produktion zu verwenden, und ich denke, wir könnten unsere Antwort haben.
hisnameisjimmy
Ich habe gerade festgestellt, dass ein Freund mit dem iPad mini OS 7 dieses Problem nicht hat. Haben Sie eine Idee, ob es sich um ein iPad mini handelt?
Gino
1
Ich habe ein iPad Mini mit Netzhaut und
sehe
Wow ... ich kann nicht glauben, dass ich so lange gebraucht habe, um das zu finden. Ich habe die ganze Nacht nach seltsamen Javascript-Hacks gesucht, die fast, aber nie funktioniert haben. Das ist großartig.
Christopher Reid
OMG verschwendete ungefähr zwei Tage damit auf dem iPad Sim und dachte über meine Position nach: absolut; verfolgte dies. Vielen Dank!
Chris Gunawardena
16

Einfache, sauberere CSS-Lösung:

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

iOS 7 scheint damit die Höhe richtig einzustellen. Es ist auch nicht erforderlich, die Größe von Javascript-Ereignissen usw. zu ändern. Da Sie mit einer App in voller Höhe arbeiten, spielt es keine Rolle, ob die Position immer fest ist.

mikeStone
quelle
Dies funktioniert auf einem normalen iPad mit Retina, aber seltsamerweise nicht auf einem iPad Mini. Das 672px-Update scheint auf beiden zu funktionieren.
Jscharf
14

Samuels Antwort, wie auch von Terry Thorsen angegeben, funktioniert hervorragend, schlägt jedoch fehl, falls die Webseite dem iOS-Home hinzugefügt wurde.

Eine intuitivere Lösung wäre, nach window.navigator.standalonevar zu suchen.

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

Auf diese Weise gilt es nur, wenn es in Safari geöffnet wird und nicht, wenn es von zu Hause aus gestartet wird.

Andrea Tondo
quelle
Eine andere Situation, in der dies nicht funktioniert, ist, wenn die Favoritenleiste angezeigt wird. Also mit dieser Antwort und meinem unten - alle Themen abgedeckt (soweit ich weiß!)
Nick H247
2

Samuels Antwort ist die beste, obwohl sie nicht funktioniert, wenn ein Benutzer die Seite zu seinem Startbildschirm hinzufügt (Startbildschirmseiten weisen den Fehler nicht auf). Überprüfen Sie die innere Höhe, bevor Sie die Klasse wie folgt hinzufügen:

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

Beachten Sie, dass der Fehler auch nicht in der Webansicht angezeigt wird.

Terry Thorsen
quelle
2
Mein iPad meldet window.innerHeight von 671 (mit console.log), sodass 672 nicht immer genau ist.
Esger
2

Ich habe diese JavaScript-Lösung verwendet, um dieses Problem zu lösen:

    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)";
}
czuendorf
quelle
1

Eine Variante von Samuels Ansatz, aber mit der Position: -webkit-sticky set on html hat bei mir am besten funktioniert.

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

Beachten Sie 'top: 0', nicht 'bottom: 0' und das Zielelement ist 'html', nicht 'body'.

übermeldet
quelle
0

Grundsätzlich gibt es zwei Fehler - die Höhe des Fensters im Querformat und die Bildlaufposition, wenn der Benutzer es im Hochformat erneut überprüft. Wir haben es so gelöst:

Die Höhe des Fensters wird gesteuert durch:

// 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);

Jetzt kann das Obige in eine Funktion eingefügt und an Fenstergrößenänderungs- und / oder Orientierungsänderungsereignisse gebunden werden. das war's ... siehe Beispiel:

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

Vadim
quelle
Sie lösen das Problem nicht wirklich, da sich am unteren Rand der Seite ein seltsamer weißer Bereich befindet (siehe hier ) und der Benutzer weiterhin durch die Seite scrollen kann.
Agudulin
0

Sie benötigen JavaScript, um diesen Fehler zu umgehen. window.innerHeighthat die richtige Höhe. Hier ist die einfachste Lösung, die ich mir vorstellen kann:

$(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();
});

Sie werden auch festlegen müssen position: fixedauf die <body>.

Hier ist ein vollständiges Arbeitsbeispiel:

<!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>
andraaspar
quelle
0

In Bezug auf die akzeptierte Antwort hatte ich auch Glück mit der folgenden Regel:

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

Dies hat den zusätzlichen Vorteil, dass das HTML-Element anscheinend nicht mehr "unter" einem festen Body-Element gescrollt wird.

Nick Maynard
quelle
0

Wenn ich das benutze:

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

Meine Safari auf dem Mac zeigt die gleichen HTML-Klassen ... SO funktioniert es nicht richtig.

Ich habe versucht, ein paar Dinge zu kombinieren - das hat bei mir funktioniert, damit ich es im Browser und ohne Browseransicht verwalten kann.

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;
   }
}

///// Damit sind Sie flexibler oder andere Betriebssysteme und Browser

user3432605
quelle
0

Ich bin auf diese Seite für das gleiche Problem gestoßen. Hier gibt es viele nützliche Antworten und andere nicht (für mich).

Ich habe jedoch eine Lösung gefunden, die in meinem Fall funktioniert und völlig unabhängig davon funktioniert, welche Betriebssystemversion und welcher Fehler jetzt oder in der Vergangenheit oder Zukunft vorliegt.

Erläuterung: Entwicklung einer Web-App (keine native App) mit mehreren Modulen fester Größe im Vollbildmodus mit dem Klassennamen "Modul"

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

welches eine Fußzeile mit dem Klassennamen "Fußzeile" enthält

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

Egal, wenn ich die Höhe der Fußzeile später auf eine andere Höhe einstelle oder sogar ihre Höhe durch ihren Inhalt festgelegt wird, kann ich diesen folgenden Code zur Korrektur verwenden:

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();
});

Dank der Fähigkeiten von Matteo Spinelli kann ich iScroll weiterhin problemlos verwenden, da die Änderungsereignisse glücklicherweise nachher ausgelöst werden. Wenn nicht, müsste der iScroll-init nach der Korrektur erneut abgerufen werden.

Hoffe das hilft jemandem

ddlab
quelle
0

Die akzeptierte Antwort kommt nicht zurecht, wenn die Favoritenleiste angezeigt wird. Hier ist ein verbesserter Catch All Fix:

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

Was ist, wenn Sie es versuchen?

html{ bottom: 0;padding:0;margin:0}body {
position: absolute;
bottom: 0;
height: 672px !important;
}
Ainos
quelle