it-swarm.com.de

CSS3 100vh im mobilen Browser nicht konstant

Ich habe ein sehr seltsames Problem ... In jedem Browser und jeder mobilen Version bin ich auf dieses Verhalten gestoßen:

  • alle Browser haben ein oberes Menü, wenn Sie die Seite laden (z. B. die Adressleiste), die beim Starten der Seite nach oben rollen.
  • 100vh werden nur für den sichtbaren Teil des Darstellungsbereichs berechnet. Wenn die Browserleiste nach oben rutscht, steigt der Wert um 100vh (in Pixeln).
  • alle Layouts werden neu gezeichnet und neu eingestellt, da sich die Abmessungen geändert haben
  • schlechter Sprungeffekt für die Benutzererfahrung

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>

133

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 .

102
nils

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.

18
user6261119

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.

Demo

11
Andreas Herd

Sie können min-height: -webkit-fill-available; in Ihrem CSS anstelle von 100vh versuchen. Es sollte gelöst werden

6
Saurabh Jain

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`);
});
3
Stijn Slats

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.

3
Jahaziel

@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.

3
klimat

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.

2
Mike

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. 

2
Ray1422

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.

1
t.j.goodman

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>

1
manuel-84

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.

1
Rico Kahler

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

0
Ray Andison

Sie können versuchen, Ihrem Container position: fixed; top: 0; bottom: 0;-Eigenschaften zu geben.

0
Hasan upinion

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.

0
turkus

Hoffentlich handelt es sich hierbei um eine UA-definierte CSS-Umgebungsvariable, wie hier vorgeschlagen: https://github.com/w3c/csswg-drafts/issues/2630#issuecomment-397536046

0
Malvoz