Ich entwickle derzeit eine responsive Site mit Twitter Bootstrap.
Die Website verfügt über ein Vollbild-Hintergrundbild für Mobilgeräte/Tablet/Desktop. Diese Bilder werden durch zwei Divs rotiert und ausgeblendet.
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 auf der Seite nach unten blättert und die Adressleiste ausgeblendet wird.
Die Website ist hier: http://lt2.daveclarke.me/
Besuchen Sie es auf einem mobilen Gerät und scrollen Sie nach unten, und Sie sollten das Bild vergrößern/verkleinern/verschieben.
Der Code, den ich für den 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 gedauert !!
Dieses Problem wird dadurch verursacht, dass die URL-Leisten schrumpfen/aus dem Weg rollen und die Größe der Divisionen # bg1 und # bg2 ändern, da sie eine Höhe von 100% und "fixiert" haben. Da das Hintergrundbild auf "Abdeckung" eingestellt ist, wird die Bildgröße position angepasst, wenn der enthaltende Bereich größer ist.
Aufgrund der Reaktionsfähigkeit der Website muss der Hintergrund skaliert werden. Ich unterhalte zwei mögliche Lösungen:
1) Stellen Sie die Höhe von # bg1, # bg2 auf 100 vh 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 Größe des Darstellungsfelds wird durch die URL-Leiste nicht beeinflusst, wenn es durch Javascript festgelegt wird. Daher kann mit Javascript eine statische Höhe für # bg1 und # bg2 basierend auf der Größe des Darstellungsbereichs festgelegt werden. Dies ist nicht die beste Lösung, da es kein reines CSS ist und beim Laden der Seite ein leichter Bildsprung auftritt. Es ist jedoch die einzige realisierbare Lösung, die ich sehe, wenn man die "vh" -Fehler von iOS betrachtet (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 merkwürdige Funktionalität und das Chaos nachdenken, das sie auf Websites bringen. Die letzte Änderung ist, dass Sie die URL-Leiste beim Laden der Seite unter iOS oder Chrome nicht mehr mithilfe von Scroll-Tricks "ausblenden" können.
BEARBEITEN: Das obige Skript funktioniert zwar perfekt, um die Größenanpassung des Hintergrunds zu verhindern, verursacht jedoch eine deutliche Lücke, wenn Benutzer nach unten scrollen. Dies liegt daran, dass der Hintergrund auf 100% der Bildschirmhöhe minus URL-Leiste eingestellt wird. Wenn wir die Höhe um 60px erhöhen, wie von Swiss vorgeschlagen, verschwindet dieses Problem. Das bedeutet, dass wir nicht die untersten 60px des Hintergrundbilds sehen können, wenn die URL-Leiste vorhanden ist. Dies verhindert jedoch, dass Benutzer eine Lücke sehen.
function resizeBackground() {
bg.height( $(window).height() + 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 keine Lücke am oberen Rand der Seite vorhanden war. Der Hintergrund sprang jedoch immer dann, wenn die Adressleiste verschwand/wieder angezeigt wurde. Neben dem Javascript-Fix habe ich also transition: height 999999s
auf das div angewendet. Dadurch wird ein Übergang mit einer Dauer erstellt, die das Element praktisch einfriert.
Ich habe eine ähnliche Ausgabe in einem Header unserer Website.
html, body {
height:100%;
}
.header {
height:100%;
}
Dies führt bei Android Chrome zu einem sprunghaften Bildlauf, da der .header-Container neu skaliert wird, nachdem der URL-Balken ausgeblendet wurde und der Finger vom Bildschirm entfernt wurde.
CSS-Lösung:
Durch das Hinzufügen der folgenden zwei Zeilen wird verhindert, dass der URL-Balken ausgeblendet wird und der vertikale Bildlauf weiterhin möglich ist:
html {
overflow: hidden;
}
body {
overflow-y: scroll;
-webkit-overflow-scrolling:touch;
}
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. Glücklicherweise ist die Breite des Ansichtsfensters konstant und mobile Geräte haben nur ein paar unterschiedliche Seitenverhältnisse. Wenn Sie die Breite und das Seitenverhältnis bestimmen können, erhalten Sie mit ein wenig Berechnung die Höhe des Ansichtsfensters genauso wie vh soll . Hier ist der Prozess
1) Erstellen Sie eine Reihe von Medienabfragen für Seitenverhältnisse, die Sie als Ziel festlegen möchten.
verwenden Sie das Seitenverhältnis des Geräts anstelle des Seitenverhältnisses, da die Größe des letzteren geändert wird, wenn der URL-Stab verschwindet
Ich fügte dem Geräte-Seitenverhältnis "max" hinzu, um alle Seitenverhältnisse zu berücksichtigen, die zufällig zwischen den beliebtesten liegen. Sie sind zwar nicht so präzise, aber sie werden nur für eine Minderheit der Benutzer sein und sind dennoch ziemlich nahe am richtigen vh.
erinnern Sie sich an die Medienabfrage mit horizontal/vertikal, so dass Sie für Portait die Zahlen umdrehen müssen
2) Multiplizieren Sie für jede Medienabfrage den Prozentsatz der vertikalen Höhe, für den das Element in vw sein soll, mit der Umkehrung des Seitenverhältnisses.
3) Sie müssen die Höhe der URL-Leiste bestimmen und diese dann von der Höhe abziehen. Ich habe keine exakten Maße gefunden, aber ich verwende 9% für mobile Geräte in der Landschaft, und das scheint ziemlich gut zu funktionieren.
Dies ist keine sehr elegante Lösung, aber auch die anderen Optionen sind nicht sehr gut, wenn man bedenkt, dass sie:
Wenn Ihre Website für den Benutzer fehlerhaft erscheint,
mit ungeeigneten Elementen, oder
Verwenden von Javascript für einige grundlegende Styling,
Der Nachteil ist, dass einige Geräte andere URL-Stabhöhen oder Seitenverhältnisse haben als die gängigsten. Wenn jedoch diese Methode angewendet wird, wenn nur eine kleine Anzahl von Geräten die Addition/Subtraktion einiger Pixel erleidet, erscheint mir dies viel besser als jeder, der über eine Website verfügt, wenn er die Größe ändert.
Um es einfacher zu machen, 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%);
}
}
Alle Antworten hier verwenden window
height, die von der URL-Leiste beeinflusst wird. Hat jeder die screen
Höhe 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 das Hinzufügen des Teils .css()
wird das zwangsläufig nach oben ausgerichtete, absolut positionierte Element nach unten ausgerichtet, sodass überhaupt kein Sprung erfolgt. Ich denke jedoch, dass es keinen Grund gibt, das nicht direkt in das normale CSS einzufügen.
Wir benötigen den User Agent Sniffer, da die Bildschirmhöhe auf Desktops nicht hilfreich ist.
Dies alles setzt auch voraus, dass #background
ein Element mit fester Position ist, das das Fenster ausfüllt.
Für die JavaScript-Puristen (Warnung - nicht getestet):
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: Es tut uns leid, dass dies Ihr spezifisches Problem nicht direkt mit mehr als einem Hintergrund löst. Dies ist jedoch eines der ersten Ergebnisse bei der Suche nach diesem Problem fester Hintergründe, die auf dem Handy springen.
Ich bin auch auf dieses Problem gestoßen, als ich versuchte, einen Eingangsbildschirm zu erstellen, der den gesamten Ansichtsbereich abdeckt. Leider funktioniert die akzeptierte Antwort nicht mehr.
1) Elemente, deren Höhe auf 100vh
eingestellt ist, werden bei jeder Änderung der Größe des Ansichtsfensters in der Größe geändert, einschließlich der Fälle, in denen dies durch (nicht) erscheinende URL-Leisten 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 mit transition: height 999999s
"einzufrieren", wie in der Antwort von AlexKempton vorgeschlagen. Der Nachteil ist, dass dadurch die Anpassung an alle Änderungen der Ansichtsfenstergröße, einschließlich der durch das Drehen des Bildschirms verursachten, effektiv deaktiviert wird.
Meine Lösung besteht also darin, Viewport-Änderungen 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);
BEARBEITEN: Ich verwende diese Technik tatsächlich zusammen mit height: 100vh
. Die Seite wird von Anfang an richtig gerendert. Anschließend wird das Javascript aktiviert und die Höhe wird manuell verwaltet. Auf diese Weise wird beim Laden der Seite (oder sogar danach) überhaupt kein Flackern ausgeführt.
Die Lösung, die ich derzeit verwende, besteht darin, die Variable userAgent
auf $(document).ready
zu überprüfen, um festzustellen, ob es sich um einen der beleidigenden Browser handelt. Wenn ja, folgen Sie diesen Schritten:
$(window).resize
die relevanten Höhenwerte nur, wenn sich die neue Ansichtsdimension horizontal von ihrem Anfangswert unterscheidet Optional können Sie auch das Erlauben vertikaler Größenänderungen nur testen, wenn diese über der Höhe der Adressleiste (n) liegen.
Oh, und die Adressleiste wirkt sich auf $(window).height
aus. Siehe: Adressleiste des Mobile Webkit-Browsers (Chrome) $ (Fenster) .height (); Hintergrundgröße erstellen: Cover jedes Mal neu skalierenJS "Window" width-height vs. "screen" width-height?
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;
Das alles verzögert die Bewegung so, dass sie unglaublich langsam ist und nicht auffällt.
Ich habe eine Vanilla-Javascript-Lösung für die Verwendung von VH-Einheiten entwickelt. Die Verwendung von VH wird praktisch überall durch Adressleisten bewirkt, die beim Scrollen minimiert werden. Um den Jank zu korrigieren, der angezeigt wird, wenn die Seite neu gezeichnet wird, habe ich hier ein js, das alle Ihre Elemente mit VH-Einheiten (wenn Sie ihnen die Klasse .vh-fix
geben) erfasst und ihnen inline Pixelhöhe gibt. Sie werden im Wesentlichen auf der gewünschten Höhe eingefroren. Sie können dies bei Rotation oder Änderung der Ansichtsfenstergröße tun, um ansprechbar 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, ich hoffe es hilft.
dies ist meine Lösung, um dieses Problem zu beheben. Ich habe direkt Kommentare zum Code hinzugefügt. __ Ich habe diese Lösung getestet und funktioniert einwandfrei. Ich hoffe, wir werden für alle nützlich sein, 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
});
};
Meine Lösung beinhaltete ein bisschen Javascript. Behalten Sie 100% oder 100 vh auf dem div bei (dies verhindert, dass das div beim ersten Laden der Seite nicht erscheint). Wenn die Seite dann geladen wird, greifen Sie die Fensterhöhe und wenden Sie sie auf das betreffende Element an. Vermeidet den Sprung, da Sie jetzt eine statische Höhe in Ihrem div haben.
var $hero = $('#hero-wrapper'),
h = window.innerHeight;
$hero.css('height', h);
Dies ist die beste (einfachste) Lösung über alles, was ich versucht habe.
... und das hält nicht die native Erfahrung der Adressleiste!
Sie können beispielsweise die Höhe mit CSS auf 100% setzen und dann mit Javascript die Höhe der Fensterhöhe in px auf 0,9 * setzen, wenn das Dokument geladen wird.
Zum Beispiel mit jQuery:
$("#element").css("height", 0.9*$(window).height());
)
Leider funktioniert nichts mit reinem CSS: P, aber seien Sie auch vorsichtig, dass vh
und vw
auf iPhones fehlerhaft sind - verwenden Sie Prozentsätze.
Ich setze mein Breitenelement mit Javascript. Nachdem ich die 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 für mich. Ich benutze kein Jquery-Ect. weil ich möchte, dass es so bald wie möglich geladen wird.
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: after position: fixed; Hack hier .
IE: Hintergrundgröße: 901px; für alle Bildschirme <900px? Nicht perfekt oder reaktionsschnell, aber ich habe auf Mobile <480px einen Zauber erlebt, da ich eine abstrakte BG benutze.
Es hat einige Stunden gedauert, bis Sie alle Details dieses Problems verstanden und die beste Implementierung herausgefunden haben. Ab April 2016 stellt sich heraus, dass nur iOS Chrome dieses Problem hat. Ich habe es mit Android Chrome und iOS Safari ausprobiert - beide waren ohne dieses Update in Ordnung. Das Update für iOS Chrome, das ich verwende, ist:
$(document).ready(function() {
var screenHeight = $(window).height();
$('div-with-background-image').css('height', screenHeight + 'px');
});
Die Lösung, die ich bei einem ähnlichen Problem hatte, bestand darin, die Elementhöhe bei jedem touchmove
-Ereignis auf window.innerHeight
zu setzen.
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);
}
});
Dies macht das Element zu jeder Zeit exakt 100% des verfügbaren Bildschirms aus, nicht mehr und nicht weniger. Auch während der Adressleiste verstecken oder anzeigen.
Trotzdem ist es schade, dass wir solche Patches finden müssen, bei denen einfache position: fixed
funktionieren sollte.
Ähnlich wie bei @AlexKempton. (konnte mich nicht entschuldigen)
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 die Größenänderung des Elements auch beim Drehen des Geräts verhindert wird. Sie könnten jedoch JS verwenden, um orientationchange
zu erkennen und die Höhe zurückzusetzen, falls dies ein Problem war.
Ich verwende diese Problemumgehung: Fixiere die Höhe von bg1 beim Laden der Seite durch:
var BG = document.getElementById('bg1');
BG.style.height = BG.parentElement.clientHeight;
Fügen Sie anschließend einen Listener für die Größenänderung von Window hinzu, der Folgendes ausführt: Wenn der Höhenunterschied nach der Größenänderung weniger als 60px ist (etwas mehr als die Höhe der URL-Leiste), dann nichts tun, und wenn er größer als 60px ist, setzen Sie die Höhe von bg1 erneut auf Höhe der Eltern 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!
Für diejenigen, die die tatsächliche Innenhöhe und den vertikalen Bildlauf des Fensters hören möchten, während der Chrome-Browser die URL-Leiste von angezeigt auf verborgen und umgekehrt umstellt, besteht die einzige Lösung darin, eine Intervallfunktion festzulegen Messen Sie die Diskrepanz des window.innerHeight
mit seinem 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 ist. Kennt jemand eine bessere Lösung?