Ich habe ein sehr seltsames Problem ... In jedem Browser und jeder mobilen Version bin ich auf dieses Verhalten gestoßen:
wie kann dieses Problem vermieden werden? Als ich zum ersten Mal von Viewport-Height erfuhr, war ich aufgeregt und dachte, ich könnte es für Blöcke mit fester Höhe verwenden, die mit JavaScript zu tun haben, aber jetzt denke ich, der einzige Weg, dies zu tun, ist in der Tat Javascript mit etwas Größenänderungsereignis ...
sie können das Problem an folgender Stelle sehen: Beispielseite
Kann mir jemand mit einer CSS-Lösung helfen/vorschlagen?
einfacher Testcode:
/* 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>
Leider ist das absichtlich…
Dies ist ein bekanntes Problem (zumindest in Safari Mobile), das beabsichtigt ist, da andere Probleme vermieden werden. Benjamin Poulain hat auf einen Webkit-Fehler geantwortet :
Dies ist völlig beabsichtigt. Um diesen Effekt zu erzielen, war unsere Arbeit einiges an Arbeit. :)
Das Grundproblem ist folgendes: Der sichtbare Bereich ändert sich beim Scrollen dynamisch. Wenn wir die Höhe des CSS-Ansichtsfensters entsprechend aktualisieren, müssen wir das Layout während des Bildlaufs aktualisieren. Nicht nur das sieht nach Scheiße aus, aber das ist bei 60 FPS auf den meisten Seiten praktisch unmöglich (60 FPS ist die Basis-Framerate für iOS).
Es ist schwer, Ihnen den Teil "sieht aus wie Scheiße" zu zeigen, aber Sie können sich beim Scrollen vorstellen, dass sich der Inhalt bewegt und die gewünschten Elemente auf dem Bildschirm ständig verschoben werden.
Das dynamische Aktualisieren der Höhe funktionierte nicht. Wir hatten ein paar Auswahlmöglichkeiten: Dropport-Ansichtsfenster unter iOS abgleichen, Dokumentgröße wie vor iOS 8 anpassen, kleine Ansichtsgröße verwenden, große Ansichtsgröße.
Von den Daten, die wir hatten, war die Verwendung der größeren Ansicht der beste Kompromiss. Die meisten Websites mit Viewport-Einheiten sahen die meiste Zeit großartig aus.
Nicolas Hoizey hat dies ziemlich recherchiert: https://nicolas-hoizey.com/2015/02/viewportheight-is-taller-than-the-visible-part-of-the-ocument-in- einige-mobile-browser.html
Kein Fix geplant
An diesem Punkt können Sie nicht viel tun, außer auf Viewport-Höhe auf mobilen Geräten zu verzichten. Mobile Chrome scheint dies auch anpassen zu wollen, obwohl es nicht sicher ist, ob sie durchlaufen werden .
Für viele Websites, die ich baue, fragt der Client nach einem 100-V-Banner und genau wie Sie es gefunden haben, führt dies zu einer schlechten "springenden" Erfahrung auf dem Handy, wenn Sie mit dem Blättern beginnen. So löse ich das Problem für ein reibungsloses, konsistentes Erlebnis auf allen Geräten:
Ich habe mein Bannerelement CSS zuerst auf height:100vh
gesetzt.
Dann verwende ich jQuery, um die Höhe des Bannerelements in Pixeln zu ermitteln, und wende einen Inline-Stil mit dieser Höhe an.
var viewportHeight = $('.banner').outerHeight();
$('.banner').css({ height: viewportHeight });
Auf diese Weise wird das Problem auf mobilen Geräten gelöst, da beim Laden der Seite das Bannerelement mit CSS auf 100 vh gesetzt wird. JQuery überschreibt dies, indem es Inline-CSS in mein Bannerelement einfügt.
Wenn jedoch auf einem Desktop ein Browserfenster seine Größe ändert, ändert sich die Größe meines Bannerelements nicht, da es aufgrund der obigen jQuery jetzt eine feste Höhe in Pixeln hat. Um dies anzusprechen, füge ich Mobile Detect hinzu, um dem Hauptteil meines Dokuments eine "mobile" Klasse hinzuzufügen. Und dann wickle ich die obige jQuery in eine if-Anweisung ein:
if ($('body').hasClass('mobile')) {
var viewportHeight = $('.banner').outerHeight();
$('.banner').css({ height: viewportHeight });
}
Wenn sich ein Benutzer auf einem mobilen Gerät befindet, befindet sich die Klasse "mobile" im Körper meiner Seite, und die obige jQuery wird ausgeführt. Mein Bannerelement wird also nur das Inline-CSS auf mobilen Geräten verwenden, während auf dem Desktop die ursprüngliche CSS-Regel von 100vh erhalten bleibt.
in meiner App mache ich das so (TypeScript und verschachtelte Postcss, ändern Sie den Code entsprechend):
const appHeight = () => {
const doc = document.documentElement
doc.style.setProperty('--app-height', `${window.innerHeight}px`)
}
window.addEventListener('resize', appHeight)
appHeight()
in deinem css:
:root {
--app-height: 100%;
}
html,
body {
padding: 0;
margin: 0;
overflow: hidden;
width: 100vw;
height: 100vh;
@media not all and (hover:hover) {
height: var(--app-height);
}
}
es funktioniert zumindest auf Chrome Mobile und iPad. Was nicht funktioniert, ist, wenn Sie Ihre App unter iOS zum Homescreen hinzufügen und die Ausrichtung ein paar Mal ändern. Irgendwie vermischen sich die Zoomstufen mit dem Wert von innerHeight. Ich könnte ein Update posten, wenn ich eine Lösung finde.
Sie können min-height: -webkit-fill-available;
in Ihrem CSS anstelle von 100vh
versuchen. Es sollte gelöst werden
Dies ist der Trick, den Sie benötigen https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ .
CSS
.my-element {
height: 100vh; /* Fallback for browsers that do not support Custom Properties */
height: calc(var(--vh, 1vh) * 100);
transition: 1s; /* To avoid a jumpy result */
}
JS
// First we get the viewport height and we multiple it by 1% to get a value for a vh unit
let vh = window.innerHeight * 0.01;
// Then we set the value in the --vh custom property to the root of the document
document.documentElement.style.setProperty('--vh', `${vh}px`);
// We listen to the resize event
window.addEventListener('resize', () => {
// We execute the same script as before
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
Ich habe gerade eine von mir entworfene Web-App mit diesem Problem bei iPhones und iPads gefunden und einen Artikel gefunden, der angibt, sie mit Medienanfragen zu lösen, die auf bestimmte Apple-Geräte abzielen.
Ich weiß nicht, ob ich den Code aus diesem Artikel hier freigeben kann, aber die Adresse lautet: http://webdesignerwall.com/tutorials/css-fix-for-ios-vh-unit-bug
Zitat des Artikels: "Passen Sie die Elementhöhe einfach mit der Gerätehöhe an, indem Sie Medienabfragen verwenden, die auf ältere Versionen von iPhone und iPad abzielen."
Sie fügten nur 6 Medienabfragen hinzu, um Elemente mit voller Höhe anzupassen, und es sollte funktionieren, da es vollständig CSS implementiert ist.
Bearbeiten in Bearbeitung: Ich kann es momentan nicht testen, aber ich werde zurückkommen und meine Ergebnisse berichten.
@nils hat es klar erklärt.
Was kommt als nächstes
Ich bin gerade zurückgegangen, um relative 'classic'%
(Prozentsatz) in CSS zu verwenden.
Es ist oft mehr Aufwand, etwas zu implementieren, als dies vh
wäre, aber zumindest haben Sie eine ziemlich stabile Lösung, die auf verschiedenen Geräten und Browsern ohne merkwürdige UI-Störungen funktioniert.
Ich habe eine React-Komponente entwickelt - check it out Wenn Sie React verwenden oder - Durchsuchen Sie den Quellcode Wenn Sie dies nicht tun, können Sie ihn an Ihre Umgebung anpassen.
Sie setzt die Höhe des Vollbilddivs auf window.innerHeight
und aktualisiert sie dann bei der Größenänderung des Fensters.
Der folgende Code hat das Problem gelöst (mit jQuery).
var vhHeight = $("body").height();
var chromeNavbarHeight = vhHeight - window.innerHeight;
$('body').css({ height: window.innerHeight, marginTop: chromeNavbarHeight });
Und die anderen Elemente verwenden %
als Einheit, um vh
zu ersetzen.
Da ich neu bin, kann ich andere Antworten nicht kommentieren.
Wenn jemand nach einer Antwort sucht, um dieses Problem zu lösen (und Javascript verwenden kann - da dies im Moment erforderlich erscheint, um dieses Problem zu lösen), hat dieser Ansatz für mich ziemlich gut funktioniert, und es ist auch eine Änderung der mobilen Orientierung. Ich benutze Jquery für den Beispielcode, sollte aber mit vanillaJS möglich sein.
Zuerst verwende ich ein Skript, um festzustellen, ob es sich bei dem Gerät um Berührung oder Schwebeflug handelt. Nackte Knochen Beispiel:
if ("ontouchstart" in document.documentElement) {
document.body.classList.add('touch-device');
} else {
document.body.classList.add('hover-device');
}
Dies fügt dem body-Element eine Klasse hinzu, je nach Gerätetyp (Schwebeflug oder Berührung), der später für das Height-Script verwendet werden kann.
-Next Verwenden Sie diesen Code, um die Höhe des Geräts beim Laden und bei Änderung der Ausrichtung festzulegen:
if (jQuery('body').hasClass("touch-device")) {
//Loading height on touch-device
function calcFullHeight() {
jQuery('.hero-section').css("height", $(window).height());
}
(function($) {
calcFullHeight();
jQuery(window).on('orientationchange', function() {
// 500ms timeout for getting the correct height after orientation change
setTimeout(function() {
calcFullHeight();
}, 500);
});
})(jQuery);
} else {
jQuery('.hero-section').css("height", "100vh");
}
-Timeout ist so eingestellt, dass das Gerät bei einer Änderung der Ausrichtung die neue Höhe korrekt berechnet. Wenn es keine Zeitüberschreitung gibt, ist die Höhe nach meiner Erfahrung nicht korrekt. 500ms könnten eine Überforderung sein, hat aber für mich gearbeitet.
-100vh auf Hover-Geräten ist ein Fallback, wenn der Browser CSS 100vh überschreibt.
Schauen Sie sich diese Antwort an: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
// First we get the viewport height and we multiple it by 1% to get a value for a vh unit
let vh = window.innerHeight * 0.01;
// Then we set the value in the --vh custom property to the root of the document
document.documentElement.style.setProperty('--vh', `${vh}px`);
// We listen to the resize event
window.addEventListener('resize', () => {
// We execute the same script as before
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
body {
background-color: #333;
}
.module {
height: 100vh; /* Use vh as a fallback for browsers that do not support Custom Properties */
height: calc(var(--vh, 1vh) * 100);
margin: 0 auto;
max-width: 30%;
}
.module__item {
align-items: center;
display: flex;
height: 20%;
justify-content: center;
}
.module__item:nth-child(odd) {
background-color: #fff;
color: #F73859;
}
.module__item:nth-child(even) {
background-color: #F73859;
color: #F1D08A;
}
<div class="module">
<div class="module__item">20%</div>
<div class="module__item">40%</div>
<div class="module__item">60%</div>
<div class="module__item">80%</div>
<div class="module__item">100%</div>
</div>
Folgendes hat für mich gearbeitet:
html { height: 100vh; }
body {
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100vw;
}
/* this is the container you want to take the visible viewport */
/* make sure this is top-level in body */
#your-app-container {
height: 100%;
}
Die Variable body
nimmt die Höhe des sichtbaren Ansichtsfensters an und #your-app-container
mit height: 100%
bewirkt, dass der Container die sichtbare Höhe des Viewport nimmt.
Die Verwendung von vh auf Mobilgeräten funktioniert nicht mit 100vh, da bei der Auswahl des Designs die gesamte Höhe des Geräts ohne Adressleisten usw. berücksichtigt wird.
Wenn Sie nach einem Layout mit Teilungshöhen suchen, die proportional zur tatsächlichen Ansichtshöhe sind, verwende ich die folgende reine CSS-Lösung:
:root {
--devHeight: 86vh; //*This value changes
}
.div{
height: calc(var(--devHeight)*0.10); //change multiplier to suit required height
}
Sie haben zwei Möglichkeiten, um die Höhe des Ansichtsfensters festzulegen. Stellen Sie --devHeight manuell auf eine Höhe ein, die funktioniert (Sie müssen diesen Wert jedoch für jeden Gerätetyp eingeben, für den Sie codieren).
oder
Verwenden Sie Javascript, um die Fensterhöhe zu ermitteln, und aktualisieren Sie dann --devheight beim Laden und Aktualisieren des Ansichtsfensters (dies erfordert jedoch Javascript und ist keine reine CSS-Lösung).
Sobald Sie die richtige Ansichtshöhe erhalten haben, können Sie mehrere Divs mit einem genauen Prozentsatz der Gesamthöhe des Ansichtsfensters erstellen, indem Sie einfach den Multiplikator in jedem Div ändern, dem Sie die Höhe zuweisen.
0,10 = 10% der Ansichtshöhe 0,57 = 57% der Ansichtshöhe
Hoffe das könnte jemandem helfen;)
Sie können versuchen, Ihrem Container position: fixed; top: 0; bottom: 0;
-Eigenschaften zu geben.
Da es nicht behoben wird, können Sie Folgendes tun:
# html
<body>
<div class="content">
<!-- Your stuff here -->
</div>
</body>
# css
.content {
height: 80vh;
}
Für mich war es die schnellste und reinere Lösung als mit dem JavaScript zu spielen, das auf vielen Geräten und Browsern nicht funktioniert.
Verwenden Sie einfach den richtigen Wert von vh
, der Ihren Anforderungen entspricht.
Hoffentlich handelt es sich hierbei um eine UA-definierte CSS-Umgebungsvariable, wie hier vorgeschlagen: https://github.com/w3c/csswg-drafts/issues/2630#issuecomment-397536046