Das Hintergrundbild springt, wenn die Adressleiste iOS / Android / Mobile Chrome verbirgt

172

Ich entwickle derzeit eine reaktionsfähige Website mit Twitter Bootstrap.

Die Site verfügt über ein Hintergrundbild im Vollbildmodus für Mobilgeräte / Tablets / Desktops. Diese Bilder drehen und verblassen jeweils mit zwei Divs.

Es ist fast perfekt, bis auf ein Problem. Bei Verwendung von iOS Safari, Android Browser oder Chrome unter Android springt der Hintergrund leicht, wenn ein Benutzer einen Bildlauf auf der Seite durchführt und die Adressleiste ausgeblendet wird.

Die Seite ist hier: http://lt2.daveclarke.me/

Besuchen Sie es auf einem mobilen Gerät und scrollen Sie nach unten. Das Bild sollte in der Größe geändert / verschoben werden.

Der Code, den ich für das Hintergrund-DIV verwende, lautet wie folgt:

#bg1 {
    background-color: #3d3d3f;
    background-repeat:no-repeat;
    background-attachment:fixed;
    background-position:center center;
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover; position:fixed;
    width:100%;
    height:100%;
    left:0px;
    top:0px;
    z-index:-1;
    display:none;
}

Alle Vorschläge sind willkommen - das hat mir schon eine Weile den Kopf zerbrochen !!

Dave Clarke
quelle
Ihr Link erfordert auth ... zeigen Sie uns auch einige Code pls!
Shawn Taylor
Neuer Link hinzugefügt & Code für die Hintergrundpositionierung usw. angezeigt
Dave Clarke
1
Wenn dieses Problem auftritt, überprüfen Sie möglicherweise developer.google.com/web/updates/2016/12/url-bar-resizing . Dieses Problem wurde jetzt (irgendwie) behoben, betrifft jedoch immer noch Elemente, die dies getan haben position: fixed.
Adam Reis
@AdamReis Endlich! Vielen Dank für die Veröffentlichung
Dave Clarke

Antworten:

106

Dieses Problem wird dadurch verursacht, dass die URL-Balken verkleinern / aus dem Weg rutschen und die Größe der Divs # bg1 und # bg2 ändern, da sie 100% hoch und "fest" sind. Da das Hintergrundbild auf "Abdeckung" eingestellt ist, wird die Bildgröße / -position angepasst, wenn der enthaltende Bereich größer ist.

Basierend auf der Reaktionsfähigkeit der Site muss der Hintergrund skaliert werden. Ich unterhalte zwei mögliche Lösungen:

1) Stellen Sie die Höhe # bg1, # bg2 auf 100vh ein. Theoretisch ist dies eine elegante Lösung. IOS hat jedoch einen vh-Fehler ( http://thatemil.com/blog/2013/06/13/viewport-relative-unit-strangeness-in-ios-6/ ). Ich habe versucht, eine maximale Höhe zu verwenden, um das Problem zu verhindern, aber es blieb bestehen.

2) Die von Javascript bestimmte Größe des Ansichtsfensters wird von der URL-Leiste nicht beeinflusst. Daher kann Javascript verwendet werden, um eine statische Höhe für # bg1 und # bg2 basierend auf der Größe des Ansichtsfensters festzulegen. Dies ist nicht die beste Lösung, da es sich nicht um reines CSS handelt und beim Laden der Seite ein leichter Bildsprung auftritt. Es ist jedoch die einzige praktikable Lösung, die ich unter Berücksichtigung der "vh" -Fehler von iOS sehe (die in iOS 7 nicht behoben zu sein scheinen).

var bg = $("#bg1, #bg2");

function resizeBackground() {
    bg.height($(window).height());
}

$(window).resize(resizeBackground);
resizeBackground();

Nebenbei bemerkt, ich habe so viele Probleme mit diesen Größenänderungs-URL-Leisten in iOS und Android gesehen. Ich verstehe den Zweck, aber sie müssen wirklich über die seltsame Funktionalität und das Chaos nachdenken, das sie auf Websites verursachen. Die letzte Änderung ist, dass Sie die URL-Leiste beim Laden von Seiten unter iOS oder Chrome nicht mehr mithilfe von Bildlauftricks "ausblenden" können.

BEARBEITEN: Während das obige Skript perfekt funktioniert, um die Größenänderung des Hintergrunds zu verhindern, verursacht es eine merkliche Lücke, wenn Benutzer nach unten scrollen. Dies liegt daran, dass der Hintergrund auf 100% der Bildschirmhöhe abzüglich der URL-Leiste verkleinert wird. Wenn wir die Höhe um 60 Pixel erhöhen, wie es die Schweiz vorschlägt, verschwindet dieses Problem. Es bedeutet, dass wir die unteren 60 Pixel des Hintergrundbilds nicht sehen können, wenn die URL-Leiste vorhanden ist, aber es verhindert, dass Benutzer jemals eine Lücke sehen.

function resizeBackground() {
    bg.height( $(window).height() + 60);
}
Jason
quelle
Danke dafür. Ich werde es morgen versuchen und dich wissen lassen, wie es mir geht :)
Dave Clarke
4
Das ist wunderbar. Ich habe Ihre zweite Lösung implementiert, die mit nur wenigen Pixel Abstand zwischen Fußzeile und Hintergrundbild nahezu perfekt funktioniert hat. Ich habe Ihre 4. Codezeile in: geändert, bg.height(jQuery(window).height() + 60);was auf allen meinen Geräten wunderbar funktioniert! Danke :)
Dave Clarke
6
Der iOS vh-Fehler wurde in iOS8 behoben, das Problem unter Android jedoch nicht. Ich benutze vhEinheiten und ist natürlich 100vhgrößer, wenn die Adressleiste ausgeblendet ist. Es ist dumm, dass dieser Sprung auftritt, nachdem das Scrollen aufgehört hat. Es sieht einfach fehlerhaft aus. Am Ende habe ich den Übergang auf der Höhe verwendet, um ihn absichtlich erscheinen zu lassen.
Probleme von
1
Ich konnte dieses Problem lösen, indem ich den Hintergrund von einem bodyin einen Wrapper <div>verschob, der den gesamten Inhalt der Seite umhüllte. Keine springenden Hintergründe auf iOS oder Android!
Marius Schulz
2
Die JS-Lösung funktioniert bei mir nicht (Android). Bestätigt, dass das Skript die Höhe festlegt, das Problem jedoch weiterhin besteht.
Jwinn
60

Ich stellte fest, dass Jasons Antwort für mich nicht ganz funktionierte und ich immer noch einen Sprung bekam. Das Javascript stellte sicher, dass oben auf der Seite keine Lücke vorhanden war, aber der Hintergrund sprang immer noch, wenn die Adressleiste verschwand / wieder auftauchte. Also habe ich mich neben dem Javascript-Fix auch transition: height 999999sfür das div beworben . Dies erzeugt einen Übergang mit einer Dauer, die so lang ist, dass das Element praktisch eingefroren wird.

AlexKempton
quelle
23
Sie, Sir, verdienen +1 für das echte Out-of-the-Box-Denken. Leider wird dadurch verhindert, dass die div-Größe an Änderungen der Bildschirmgröße angepasst wird, einschließlich beispielsweise der durch die Bildschirmdrehung verursachten.
Tobik
+1 für Kreativität! Möglicherweise müssen Sie dies vorerst als Problemverbindung verwenden, wenn Sie die Schriftgröße in diesem übergeordneten Container verwenden vwoder vhfestlegen.
Robabby
6
@tobik Es ist immer noch möglich, den durch die Änderung des Ansichtsfensters verursachten Sprung zu reduzieren, indem ein Übergang von
ungefähr
7
Versuchen Sie jetzt, das Telefon zu drehen
Cuddlecheek
1
@tobik das macht es eigentlich mehr ein Feature als ein Bug;) gutes Denken
dimitrieh
23

Ich habe ein ähnliches Problem in einem Header unserer Website.

html, body {
    height:100%;
}
.header {
    height:100%;
}

Dies führt zu einem nervösen Bildlauf auf Android Chrome, da der .header-Container neu skaliert wird, nachdem sich die URL-Leiste versteckt und der Finger vom Bildschirm entfernt wurde.

CSS-Lösung:

Durch Hinzufügen der folgenden zwei Zeilen wird verhindert, dass die URL-Leiste ausgeblendet wird und vertikales Scrollen weiterhin möglich ist:

html {
    overflow: hidden;
}
body {
    overflow-y: scroll;
    -webkit-overflow-scrolling:touch;
}
Matte
quelle
4
Ja, das löst es, wie Sie sagen, aber es ist schade, dass die Navigationsleiste immer angezeigt wird. Auf einigen Handys kann dies einen Teil des wertvollen Platzes auf dem Bildschirm einnehmen!
Dave Clarke
1
Um dies zu verhindern, können Sie zusätzlich eine JavaScript-Problemumgehung verwenden. Dieses Beispiel funktioniert jedoch überhaupt ohne JS.
Matte
3
Das Scrollen ist vollständig deaktiviert, als ich diese Lösung ausprobiert habe.
Nithin Baby
1
Danke, das hat für meine Situation super funktioniert! Sollte für alle anderen erwähnt werden, die es möglicherweise übersehen, dass die HTML- und Body-Tags auf 100% Höhe eingestellt werden müssen, damit dies funktioniert (ich habe Ihre Antwort zunächst nur überflogen und bin zur ersten Erwähnung von "Lösung" gesprungen).
Brennen
-webkit-overflow-scrolling sollte nicht an Produktionsstandorten verwendet werden. developer.mozilla.org/en-US/docs/Web/CSS/…
Fredrik Westerlund
16

Das Problem kann mit einer Medienabfrage und etwas Mathematik gelöst werden. Hier ist eine Lösung für eine Portait-Orientierung:

@media (max-device-aspect-ratio: 3/4) {
  height: calc(100vw * 1.333 - 9%);
}
@media (max-device-aspect-ratio: 2/3) {
  height: calc(100vw * 1.5 - 9%);
}
@media (max-device-aspect-ratio: 10/16) {
  height: calc(100vw * 1.6 - 9%);
}
@media (max-device-aspect-ratio: 9/16) {
  height: calc(100vw * 1.778 - 9%);
}

Da sich vh ändert, wenn die URL-Leiste verschwindet, müssen Sie die Höhe auf andere Weise bestimmen. Zum Glück ist die Breite des Ansichtsfensters konstant und mobile Geräte haben nur wenige unterschiedliche Seitenverhältnisse. Wenn Sie die Breite und das Seitenverhältnis bestimmen können, erhalten Sie mit ein wenig Mathematik die Höhe des Ansichtsfensters genau so, wie vh funktionieren sollte . Hier ist der Prozess

1) Erstellen Sie eine Reihe von Medienabfragen für Seitenverhältnisse, auf die Sie abzielen möchten.

  • Verwenden Sie das Geräte-Seitenverhältnis anstelle des Seitenverhältnisses, da letztere die Größe ändern, wenn die URL-Leiste verschwindet

  • Ich habe dem Geräte-Seitenverhältnis 'max' hinzugefügt, um alle Seitenverhältnisse zu bestimmen, die zufällig zwischen den beliebtesten folgen. Sie werden nicht so präzise sein, aber sie werden nur für eine Minderheit von Benutzern sein und werden immer noch ziemlich nah an der richtigen vh sein.

  • Denken Sie an die Medienabfrage mit horizontal / vertikal. Für Portait müssen Sie also die Zahlen umdrehen

2) Multiplizieren Sie für jede Medienabfrage den Prozentsatz der vertikalen Höhe, in dem sich das Element in vw befinden soll, mit der Umkehrung des Seitenverhältnisses.

  • Da Sie die Breite und das Verhältnis von Breite zu Höhe kennen, multiplizieren Sie einfach das gewünschte% (in Ihrem Fall 100%) mit dem Verhältnis von Höhe / Breite.

3) Sie müssen die Höhe der URL-Leiste bestimmen und diese dann von der Höhe abziehen. Ich habe keine genauen Messungen gefunden, aber ich verwende 9% für mobile Geräte im Querformat und das scheint ziemlich gut zu funktionieren.

Dies ist keine sehr elegante Lösung, aber die anderen Optionen sind auch nicht sehr gut, wenn man bedenkt:

  • Wenn Ihre Website für den Benutzer fehlerhaft erscheint,

  • Elemente mit falscher Größe haben oder

  • Verwenden von Javascript für einige grundlegende Stile,

Der Nachteil ist, dass einige Geräte möglicherweise andere URL-Balkenhöhen oder Seitenverhältnisse aufweisen als die beliebtesten. Wenn ich diese Methode jedoch verwende, wenn nur eine kleine Anzahl von Geräten einige Pixel addiert / subtrahiert, scheint mir dies viel besser zu sein als jeder, der beim Wischen die Größe einer Website ändert.

Zur Vereinfachung habe ich auch ein SASS-Mixin erstellt:

@mixin vh-fix {
  @media (max-device-aspect-ratio: 3/4) {
    height: calc(100vw * 1.333 - 9%);
  }
  @media (max-device-aspect-ratio: 2/3) {
    height: calc(100vw * 1.5 - 9%);
  }
  @media (max-device-aspect-ratio: 10/16) {
    height: calc(100vw * 1.6 - 9%);
  }
  @media (max-device-aspect-ratio: 9/16) {
    height: calc(100vw * 1.778 - 9%);
  }
}
Jordan Los
quelle
2
Sehr kreativ! Kein Fan der 9% Vermutung.
w00t
1
Sehr einfach und klug! Sie können vh-fix einen Parameter hinzufügen, um das ursprüngliche Verhalten zu simulieren: @mixin vh-fix($vh: 100)=>height: calc(100vw * (1.333 * $vh / 100) - 9%)
mjsarfatti
1
Das obige sollte sein:height: calc(100vw * (1.333 * #{$vh} / 100) - 9%)
mjsarfatti
Für meinen Anwendungsfall hat dies sehr gut funktioniert und noch besser, wenn ich das entfernt habe -9%.
Ben Fleming
12

Alle Antworten hier verwenden die windowHöhe, die von der URL-Leiste beeinflusst wird. Hat jeder die screenGröße vergessen ?

Hier ist meine jQuery-Lösung:

$(function(){

  var $w = $(window),
      $background = $('#background');

  // Fix background image jump on mobile
  if ((/Android|iPhone|iPad|iPod|BlackBerry/i).test(navigator.userAgent || navigator.vendor || window.opera)) {
    $background.css({'top': 'auto', 'bottom': 0});

    $w.resize(sizeBackground);
    sizeBackground();
  }

  function sizeBackground() {
     $background.height(screen.height);
  }
});

Durch Hinzufügen des .css()Teils wird das zwangsläufig oben ausgerichtete absolut positionierte Element in unten ausgerichtet geändert, sodass überhaupt kein Sprung erfolgt. Ich nehme jedoch an, dass es keinen Grund gibt, dies nicht direkt zum normalen CSS hinzuzufügen.

Wir brauchen den User Agent Sniffer, da die Bildschirmhöhe auf Desktops nicht hilfreich wäre.

Auch dies alles setzt voraus #background es sich um ein Element mit fester Position handelt, das das Fenster ausfüllt.

Für die JavaScript-Puristen (Warnung - ungetestet):

var background = document.getElementById('background');

// Fix background image jump on mobile
if ((/Android|iPhone|iPad|iPod|BlackBerry/i).test(navigator.userAgent || navigator.vendor || window.opera)) {
  background.style.top = 'auto';
  background.style.bottom = 0;

  window.onresize = sizeBackground;
  sizeBackground();
}

function sizeBackground() {
  background.style.height = screen.height;
}

BEARBEITEN: Entschuldigung, dass dies Ihr spezifisches Problem mit mehr als einem Hintergrund nicht direkt beantwortet. Dies ist jedoch eines der ersten Ergebnisse bei der Suche nach diesem Problem, dass feste Hintergründe auf Mobilgeräten springen.

cr0ybot
quelle
2
Ich habe eine Million dieser Antworten ausprobiert und dies ist bei weitem die beste. Ich habe ursprünglich versucht, dies nur für <body> zu verwenden, da dies den Hintergrund hatte. Die Verwendung eines Div zum Umschließen der gesamten Seite verursachte andere Probleme. Die Verwendung eines leeren Div mit dem Z-Index: -1 als Hintergrund schien die beste Lösung in Kombination mit den oben genannten zu sein. Ich habe die mobile Erkennung deaktiviert, da dies auf dem Desktop meiner Website nicht schadet. Keine Mathematik (die die Größe der Registerkarten falsch erraten kann), kein Handler für die Größenänderung erforderlich. Hintergrund ist nur der gesamte Bildschirm, der unten verankert ist. Getan. Liebe es!
Evan Langlois
9

Ich bin auch auf dieses Problem gestoßen, als ich versucht habe, einen Eingangsbildschirm zu erstellen, der das gesamte Ansichtsfenster abdeckt. Leider funktioniert die akzeptierte Antwort nicht mehr.

1) Elemente mit der Höhe eingestellt auf 100vh dass sie bei jeder Änderung der Größe des Ansichtsfensters in der Größe geändert werden, einschließlich der Fälle, in denen dies durch eine (nicht) angezeigte URL-Leiste verursacht wird.

2) $(window).height() gibt Werte zurück, die auch von der Größe der URL-Leiste beeinflusst werden.

Eine Lösung besteht darin, das Element transition: height 999999swie in der Antwort von AlexKempton vorgeschlagen "einzufrieren" . Der Nachteil besteht darin, dass dadurch die Anpassung an alle Änderungen der Ansichtsfenstergröße, einschließlich der durch die Bildschirmdrehung verursachten, effektiv deaktiviert wird.

Meine Lösung besteht also darin, Änderungen am Ansichtsfenster manuell mit JavaScript zu verwalten. Dadurch kann ich die kleinen Änderungen, die wahrscheinlich durch die URL-Leiste verursacht werden, ignorieren und nur auf die großen reagieren.

function greedyJumbotron() {
    var HEIGHT_CHANGE_TOLERANCE = 100; // Approximately URL bar height in Chrome on tablet

    var jumbotron = $(this);
    var viewportHeight = $(window).height();

    $(window).resize(function () {
        if (Math.abs(viewportHeight - $(window).height()) > HEIGHT_CHANGE_TOLERANCE) {
            viewportHeight = $(window).height();
            update();
        }
    });

    function update() {
        jumbotron.css('height', viewportHeight + 'px');
    }

    update();
}

$('.greedy-jumbotron').each(greedyJumbotron);

EDIT: Ich benutze diese Technik tatsächlich zusammen mit height: 100vh. Die Seite wird von Anfang an korrekt gerendert, und dann wird das Javascript aktiviert und die Höhe manuell verwaltet. Auf diese Weise gibt es überhaupt kein Flackern, während die Seite geladen wird (oder sogar danach).

tobik
quelle
1
Ich habe etwas Ähnliches verwendet, aber anstatt es height: 100vhim anfänglichen CSS festzulegen, habe ich es festgelegt min-height:100vhund dann beim Ändern der Fenstergröße das berechnet min-heightund es auf die Höhe des Ansichtsfensters eingestellt. Dies ist praktisch, wenn Ihre Website auf kleinen Bildschirmen angezeigt wird und der Inhalt zu groß ist, um in das Ansichtsfenster zu passen. Ein Debounce / Throttle-SetTimeout für das Größenänderungsereignis hilft bei einigen Browsern, die Leistung zu verbessern (Größenänderung wird häufig ausgelöst)
Troy Morehouse
Ich denke, dass ich zu einem bestimmten Zeitpunkt auch versucht habe, min-heightstattdessen zu verwenden, aber dann stoße ich auf ein Problem, wenn ich den inneren Inhalt vertikal zentrieren musste. Irgendwie kann die vertikale Zentrierung schwierig werden, wenn das äußere Element heighteingestellt ist auto. Also habe ich mir eine feste Mindesthöhe ausgedacht, die ausreichen sollte, um alle möglichen Inhalte zu enthalten, und diese im anfänglichen CSS festgelegt. Da min-heighthat eine höhere Priorität als height, funktioniert es ziemlich gut.
Tobik
Ah ja, ich hatte das gleiche Problem, habe es aber behoben, indem ich das Jumbotron auf display: tableund dann den internen Container auf display: table-cellmit gesetzt habe vertical-align: middle. Lief wie am Schnürchen.
Troy Morehouse
"Ja wirklich?" Weil ich den gleichen Ansatz versucht habe, aber ich bin gescheitert. Ich erinnere mich nicht wirklich, was das Problem war, aber dies könnte relevant sein: stackoverflow.com/questions/7790222/…
tobik
Stellen Sie nur sicher, dass Sie prozentuale Auffüllungen oder Ränder vermeiden. Verursachte einige seltsame Rendering-Probleme im IE8, obwohl moderne Browser in Ordnung waren.
Troy Morehouse
8

Die Lösung , die ich zur Zeit bin mit dem zu überprüfen , userAgentauf , $(document).readyum zu sehen , ob es eine des säumigen Browser ist. Wenn dies der Fall ist, führen Sie die folgenden Schritte aus:

  1. Stellen Sie die relevanten Höhen auf die aktuelle Höhe des Ansichtsfensters und nicht auf "100%" ein.
  2. Speichern Sie den horizontalen Wert des aktuellen Ansichtsfensters
  3. Dann auf $(window).resize, nur aktualisiert die entsprechenden Höhenwerte , wenn die neue horizontale Bildfenster Dimension von seinem Anfangswert abweicht
  4. Speichern Sie die neuen horizontalen und vertikalen Werte

Optional können Sie auch testen, ob vertikale Größenänderungen nur zulässig sind, wenn sie über der Höhe der Adressleiste (n) liegen.

Oh, und die Adressleiste wirkt sich aus $(window).height. Siehe: Adressleiste des Mobile Webkit-Browsers (Chrome) ändert $ (Fenster) .height (); Hintergrundgröße festlegen: Cover jedes Mal neu skalieren, wenn JS "Fenster" Breite-Höhe vs "Bildschirm" Breite-Höhe?

mp
quelle
Ich habe es nicht versucht, aber würde Ihr erster Punkt für iOS nicht funktionieren? ( thatemil.com/blog/2013/06/13/… )
Dave Clarke
Ich habe den Wert im ersten Schritt festgelegt, aber ich bin überrascht, dass Sie Jasons Antwort gefunden haben, um das Problem zu lösen. Wie bereits erwähnt, habe ich zusammen mit dem anderen Benutzer in der früheren Frage, die ich verlinkt habe, festgestellt, dass sich der Wert der Methode $ (window) .height () ändert, wenn die Adressleiste in Chrome auf Android sichtbar ist oder nicht. Ich habe diese kleine Site zusammengeschmissen, die nur das $ (Fenster) .height () -Ergebnis in einer Warnung anzeigt, und sie liefert definitiv unterschiedliche Werte auf meinem Nexus 4 in Chrom, wenn die Adressleiste nicht sichtbar ist / ist: Stormy-Wead-5908 .herokuapp.com
mp
Dies behebt das Problem auf meinem Android-Gerät zu 100%, obwohl auf meinem iPad ein ähnliches Problem auftritt, das anscheinend nicht behoben wird und das ich noch untersuche.
Dave Clarke
Können Sie Code für Ihre Lösung bereitstellen und ich werde ihn ausprobieren?
Dave Clarke
4

Ich habe eine wirklich einfache Lösung ohne die Verwendung von Javascript gefunden:

transition: height 1000000s ease;
-webkit-transition: height 1000000s ease;
-moz-transition: height 1000000s ease;
-o-transition: height 1000000s ease;

Dies verzögert lediglich die Bewegung, so dass es unglaublich langsam ist, dass es nicht wahrnehmbar ist.

Pav Sidhu
quelle
@ Tyguy7 funktioniert es gut , wenn Ihre Höhe auf einen festen Wert nicht gesetzt ist, das heißt 100%,100vh . IE8 ist der einzige große Browser, der keine Übergänge unterstützt.
Pav Sidhu
Tolle und einfache Lösung!
zdarsky.peter
3
Dies funktioniert so lange, bis Sie sich auf einem Gerät befinden, auf dem Sie von Hochformat zu Querformat wechseln können. In diesem Fall ist das Design ruiniert.
Nagy Nick
@ NagyNick das war kein so großes Problem für mich. Sie können die Orientierungsänderung in Javascript erkennen und das Hintergrundbild anpassen.
Pav Sidhu
3

Meine Lösung beinhaltete ein bisschen Javascript. Behalten Sie 100% oder 100vh auf dem div bei (dies verhindert, dass das div beim ersten Laden der Seite nicht angezeigt wird). Wenn die Seite geladen wird, nehmen Sie die Fensterhöhe und wenden Sie sie auf das betreffende Element an. Vermeidet den Sprung, da Sie jetzt eine statische Höhe auf Ihrem Div haben.

var $hero = $('#hero-wrapper'),
    h     = window.innerHeight;

$hero.css('height', h);
Todd Miller
quelle
3

Ich habe eine Vanille-Javascript-Lösung für die Verwendung von VH-Einheiten erstellt. Die Verwendung von VH wird praktisch überall durch Adressleisten bewirkt, die das Scrollen minimieren. Um den Ruck zu beheben, der beim erneuten Zeichnen der Seite angezeigt wird, habe ich diesen Js hier, der alle Ihre Elemente mit VH-Einheiten erfasst (wenn Sie ihnen die Klasse geben.vh-fix ) und ihnen inline Pixelhöhen gibt. Im Wesentlichen einfrieren in der Höhe, die wir wollen. Sie können dies bei Drehung oder bei Änderung der Größe des Ansichtsfensters tun, um reaktionsschnell zu bleiben.

var els = document.querySelectorAll('.vh-fix')
if (!els.length) return

for (var i = 0; i < els.length; i++) {
  var el = els[i]
  if (el.nodeName === 'IMG') {
    el.onload = function() {
      this.style.height = this.clientHeight + 'px'
    }
  } else {
    el.style.height = el.clientHeight + 'px'
  }
}

Dies hat alle meine Anwendungsfälle gelöst, hoffe es hilft.

Geek Devigner
quelle
3

Dies ist meine Lösung, um dieses Problem zu beheben. Ich habe Kommentare direkt zum Code hinzugefügt. Ich habe diese Lösung getestet und funktioniert einwandfrei. Ich hoffe, wir sind nützlich für alle, die das gleiche Problem haben.

//remove height property from file css because we will set it to first run of page
//insert this snippet in a script after declarations of your scripts in your index

var setHeight = function() {    
  var h = $(window).height();   
  $('#bg1, #bg2').css('height', h);
};

setHeight(); // at first run of webpage we set css height with a fixed value

if(typeof window.orientation !== 'undefined') { // this is more smart to detect mobile devices because desktop doesn't support this property
  var query = window.matchMedia("(orientation:landscape)"); //this is is important to verify if we put 
  var changeHeight = function(query) {                      //mobile device in landscape mode
    if (query.matches) {                                    // if yes we set again height to occupy 100%
      setHeight(); // landscape mode
    } else {                                                //if we go back to portrait we set again
      setHeight(); // portrait mode
    }
  }
  query.addListener(changeHeight);                          //add a listner too this event
} 
else { //desktop mode                                       //this last part is only for non mobile
  $( window ).resize(function() {                           // so in this case we use resize to have
    setHeight();                                            // responsivity resisizing browser window
  }); 
};
Linoleum
quelle
1
Sie rufen setHeight () innerhalb der changeHeight-Methode auf, wenn die Abfrage übereinstimmt und auch wenn sie nicht übereinstimmt. Entfernen Sie einfach die if-Anweisung, da dies nicht erforderlich ist.
Dennis Meissner
2

Dies ist die beste (einfachste) Lösung vor allem, was ich versucht habe.

... und dies behält nicht die native Erfahrung der Adressleiste bei !

Sie können die Höhe beispielsweise mit CSS auf 100% und dann beim Laden des Dokuments mit Javascript auf 0,9 * der Fensterhöhe in px festlegen.

Zum Beispiel mit jQuery:

$("#element").css("height", 0.9*$(window).height());

)

Leider gibt es nichts, was mit reinem CSS: P funktioniert, aber seien Sie auch so klein vhund fehlerhaft vwauf iPhones - verwenden Sie Prozentsätze.


quelle
1

Ich setze mein width-Element mit Javascript. Nachdem ich das de vh eingestellt habe.

html

<div id="gifimage"><img src="back_phone_back.png" style="width: 100%"></div>

CSS

#gifimage {
    position: absolute;
    height: 70vh;
}

Javascript

imageHeight = document.getElementById('gifimage').clientHeight;

// if (isMobile)       
document.getElementById('gifimage').setAttribute("style","height:" + imageHeight + "px");

Das funktioniert bei mir. Ich benutze kein jquery ect. weil ich möchte, dass es so schnell wie möglich geladen wird.

Johan Hoeksma
quelle
1

Es dauerte einige Stunden, um alle Details dieses Problems zu verstehen und die beste Implementierung herauszufinden. Es stellt sich heraus, dass ab April 2016 nur iOS Chrome dieses Problem hat. Ich habe Android Chrome und iOS Safari ausprobiert - beide waren ohne dieses Update in Ordnung. Das Update für iOS Chrome, das ich verwende, lautet also:

$(document).ready(function() {
   var screenHeight = $(window).height();
   $('div-with-background-image').css('height', screenHeight + 'px');
});
Littlequest
quelle
1

Einfache Antwort, wenn Ihr Hintergrund es zulässt, warum nicht die Hintergrundgröße einstellen: auf etwas, das nur die Gerätebreite mit Medienabfragen abdeckt und neben der: After-Position: fest verwendet; hier hacken .

IE: Hintergrundgröße: 901px; für irgendwelche Bildschirme <900px? Nicht perfekt oder reaktionsschnell, aber auf Mobilgeräten <480px hat es mir sehr gut gefallen, da ich einen abstrakten Hintergrund verwende.

EasterMedia
quelle
0

Ich verwende diese Problemumgehung: Korrigieren Sie die Höhe von bg1 beim Laden der Seite durch:

var BG = document.getElementById('bg1');
BG.style.height = BG.parentElement.clientHeight;

Fügen Sie dann einen Listener für Größenänderungsereignisse an Window hinzu, der Folgendes ausführt: Wenn der Höhenunterschied nach der Größenänderung weniger als 60 Pixel (mehr als die Höhe des URL-Balkens) beträgt, tun Sie nichts, und wenn er größer als 60 Pixel ist, setzen Sie die Höhe von bg1 erneut auf die Höhe des übergeordneten Elements! vollständiger Code:

window.addEventListener("resize", onResize, false);
var BG = document.getElementById('bg1');
BG.style.height = BG.parentElement.clientHeight;
var oldH = BG.parentElement.clientHeight;

function onResize() {
    if(Math.abs(oldH - BG.parentElement.clientHeight) > 60){
      BG.style.height = BG.parentElement.clientHeight + 'px';
      oldH = BG.parentElement.clientHeight;
    }
}

PS: Dieser Fehler ist so irritierend!

AadityaTaparia
quelle
0

Ähnlich wie bei @AlexKempton Antwort. (konnte leider keinen Kommentar abgeben)

Ich habe lange Übergangsverzögerungen verwendet, um die Größenänderung des Elements zu verhindern.

z.B:

transition: height 250ms 600s; /*10min delay*/

Der Nachteil dabei ist, dass verhindert wird, dass die Größe des Elements geändert wird, auch wenn sich das Gerät dreht. Sie können jedoch JS verwenden, um orientationchangedie Höhe zu erkennen und zurückzusetzen, wenn dies ein Problem darstellt.

Chris Anderson
quelle
0

Für diejenigen, die die tatsächliche innere Höhe und den vertikalen Bildlauf des Fensters hören möchten, während der mobile Chrome-Browser die URL-Leiste von "Gezeigt" in "Ausgeblendet" und umgekehrt umwandelt, ist die einzige Lösung, die ich gefunden habe, das Festlegen einer Intervallfunktion und Messen Sie die Diskrepanz von window.innerHeightmit dem vorherigen Wert.

Dies führt diesen Code ein:

var innerHeight = window.innerHeight;
window.setInterval(function ()
{
  var newInnerHeight = window.innerHeight;
  if (newInnerHeight !== innerHeight)
  {
    var newScrollY = window.scrollY + newInnerHeight - innerHeight;
    // ... do whatever you want with this new scrollY
    innerHeight = newInnerHeight;
  }
}, 1000 / 60);

Ich hoffe, dass dies praktisch sein wird. Kennt jemand eine bessere Lösung?

Édouard Mercier
quelle
0

Die Lösung, die ich bei einem ähnlichen Problem gefunden habe, bestand darin, die Höhe des Elements auf window.innerHeightjedes Mal einzustellen, wenn ein touchmoveEreignis ausgelöst wurde.

var lastHeight = '';

$(window).on('resize', function () {
    // remove height when normal resize event is fired and content redrawn
    if (lastHeight) {
        $('#bg1').height(lastHeight = '');
    }
}).on('touchmove', function () {
    // when window height changes adjust height of the div
    if (lastHeight != window.innerHeight) {
        $('#bg1').height(lastHeight = window.innerHeight);
    }
});

Dadurch überspannt das Element jederzeit genau 100% des verfügbaren Bildschirms, nicht mehr und nicht weniger. Auch während der Adressleiste versteckt oder angezeigt.

Trotzdem ist es schade, dass wir uns solche Patches einfallen lassen müssen, bei denen einfach position: fixedfunktionieren sollte.

Paul
quelle
0

Mit der Unterstützung von benutzerdefinierten CSS-Eigenschaften (Variablen) in iOS können Sie diese mit JS festlegen und nur unter iOS verwenden.

const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
if (iOS) {
  document.body.classList.add('ios');
  const vh = window.innerHeight / 100;
  document.documentElement.style
    .setProperty('--ios-10-vh', `${10 * vh}px`);
  document.documentElement.style
    .setProperty('--ios-50-vh', `${50 * vh}px`);
  document.documentElement.style
    .setProperty('--ios-100-vh', `${100 * vh}px`);
}
body.ios {
    .side-nav {
        top: var(--ios-50-vh);
    }
    section {
        min-height: var(--ios-100-vh);
        .container {
            position: relative;
            padding-top: var(--ios-10-vh);
            padding-bottom: var(--ios-10-vh);
        }
    }
}
Stephen Saucier
quelle
0

Meine Antwort ist, dass jeder, der hierher kommt (wie ich), eine Antwort auf einen Fehler findet, der durch die blanke / Browser-Oberfläche der versteckten Adresse verursacht wird.

Die ausgeblendete Adressleiste löst das Größenänderungsereignis aus. Anders als bei anderen Größenänderungsereignissen wie dem Umschalten in den Querformatmodus ändert dies jedoch nichts an der Breite des Fensters. Meine Lösung besteht also darin, sich in das Größenänderungsereignis einzuhängen und zu überprüfen, ob die Breite gleich ist.

// Keep track of window width
let myWindowWidth = window.innerWidth;

window.addEventListener( 'resize', function(event) {

    // If width is the same, assume hiding address bar
    if( myWindowWidth == window.innerWidth ) {
         return;
    }

    // Update the window width
    myWindowWidth = window.innerWidth;

    // Do your thing
    // ...
});
Erik J.
quelle