CSS3 100vh mobil tarayıcıda sabit değil


288

Çok garip bir sorunum var ... her tarayıcıda ve mobil versiyonda bu davranışla karşılaştım:

  • sayfayı yüklediğinizde (örneğin adres çubuğunu göstererek) sayfayı kaydırmaya başladığınızda yukarı kayan tüm tarayıcılarda bir üst menü bulunur.
  • 100vh bazen yalnızca görünüm penceresinin görünür kısmında hesaplanır, bu nedenle tarayıcı çubuğu 100vh yukarı kaydırıldığında (piksel cinsinden)
  • boyutlar değiştiği için tüm düzen yeniden boyama ve yeniden ayarlama
  • kullanıcı deneyimi için kötü bir ürkütücü etki

Bu sorunu nasıl önleyebiliriz? Görüntü yüksekliğini ilk duyduğumda heyecanlandım ve javascript kullanmak yerine sabit yükseklik blokları için kullanabileceğimi düşündüm, ama şimdi bunu yapmanın tek yolunun aslında bazı yeniden boyutlandırma olayıyla javascript olduğunu düşünüyorum ...

sorunu şurada görebilirsiniz: örnek site

Birisi bana bir CSS çözümü önerebilir / önerebilir mi?


basit test kodu:


1
Soruyu iyi anladıysam karşılaştığınız sorun mobil tarayıcıda yükseklik görünür görünüm yüksekliği daha fazla .. doğru?
Gaurav Aggarwal

İlginç, daha önce fark etmedim. Onun esasen arka plan resmi belirgin derecede gergin. transition: 0.5sDeğişikliği daha az aniden yapmak için a veya benzeri eklemeye ne dersiniz ?
C14L

@GauravAggarwal hayır, tam tersi: gerçek görüntü alanı yüksekliği, adres çubuğu görünür olduğunda tarayıcı tarafından sağlanan yükseklikten daha büyük ...
Nereo Costacurta

1
Sorum popüler hale geldiğinden, 5 sent vermek istiyorum: gerçek pencere yüksekliğini korumak ve sadece menü çubuğunu yukarı kaydırmak daha akıllıca olmaz mıydı? o kadar zor görünmüyor. Aslında daha kolay olmalı ... parmak yukarı -> menü çubuğu görünmez olana kadar yukarı kaydır, parmak aşağı -> menü çubuğu tamamen görünene kadar aşağı kaydırın ... hepsi yeniden ayarlama ve gerginlik etkisi olmadan vücutla birlikte ...
Nereo Costacurta

4
Google'ın bu konuda bazı iyi bilgileri var: developers.google.com/web/updates/2016/12/url-bar-resizing Vücut yüksekliğini% 100 olarak değiştirdiyseniz 100vh yerine% 100 kullanabilirsiniz
Benisburgers

Yanıtlar:


203

Ne yazık ki bu kasıtlı…

Bu, diğer sorunları önlediği için kasıtlı olarak iyi bilinen bir konudur (en azından safari mobilde). Benjamin Poulain bir webkit hatasına cevap verdi :

Bu tamamen kasıtlı. Bu etkiyi elde etmek bizim tarafımızdan biraz çalışma gerektirdi. :)

Temel sorun şudur: Siz kaydırdıkça görünür alan dinamik olarak değişir. CSS görünüm yüksekliğini buna göre güncellersek, kaydırma sırasında düzeni güncellememiz gerekir. Sadece bok gibi değil, aynı zamanda 60 FPS'de bunu yapmak çoğu sayfada neredeyse imkansızdır (60 FPS, iOS'ta temel kare hızıdır).

Size “bok gibi görünüyor” bölümünü göstermek zordur, ancak siz kaydırdıkça, içeriğin hareket ettiğini ve ekranda ne istediğinizin sürekli değiştiğini hayal edin.

Yüksekliği dinamik olarak güncellemek işe yaramadı, birkaç seçeneğimiz vardı: iOS'ta görünüm penceresi birimlerini bırakın, iOS 8'den önceki gibi belge boyutuyla eşleştirin, küçük görünüm boyutunu kullanın, büyük görünüm boyutunu kullanın.

Elimizdeki verilerden, daha büyük görüntüleme boyutunu kullanmak en iyi uzlaşma oldu. Viewport birimlerini kullanan çoğu web sitesi çoğu zaman harika görünüyordu.

Nicolas Hoizey bunu biraz araştırdı: https://nicolas-hoizey.com/2015/02/viewport-height-is-taller-than-the-visible-part-of-the-document-in-some-mobile -browsers.html

Düzeltme planlanmadı

Bu noktada, mobil cihazlarda görünüm yüksekliğini kullanmaktan kaçınmak dışında yapabileceğiniz çok şey yoktur. Chrome 2016'da da bu şekilde değişti:


7
Evet, düşündüğüm gibi. Sadece uygulanabilir çözüm, senaryolanmış bir çözümdür. Bildiğim kadarıyla, $(window).height()bu hatadan etkilenmez, bu yüzden bu şekilde gideceğim. teşekkür ederim!
Nereo Costacurta

3
Senaryo benim için tek yoldu ve mükemmel çalıştı.
captDaylight

460
Şimdiye kadarki en iç karartıcı cevap.
Winnemucca

15
Chrome 56 sürümü olduğundan, vh her zaman URL çubuğu gizliymiş gibi hesaplanır ve bu nedenle vh kaydırma dışında artmaz position:fixed. Bu, Safari'deki uygulamaya benzer. Daha fazla bilgi için: developers.google.com/web/updates/2016/12/url-bar-resizing
Kevin Farrugia

4
İlk yükten sonra en son Chrome değişmez vhveya <html> 100%yükseklik değişmez . Bu gerçekten harika - URL Çubuğu gizlendiğinde mizanpajın daralması / yeniden akması korkunç görünebilir. Firefoxve Edge Mobileyine de dinamik olarak güncelleme vhve <html>yükseklik, kaydırma sırasında tüm bileşenlerin çok fazla yırtılmasına ve yeniden boyutlandırılmasına neden oluyor, özellikle arka plan görüntüleri için
SVG'ler

143

Bunun min-height: -webkit-fill-available;yerine css'nizde deneyebilirsiniz 100vh. Çözülmüş olmalı


20
Ben desteklenmeyen min-height: 100vh;bir yedek olarak terk ediyorum -webkit-fill-available.
Tammy Tee

Vay canına, teşekkür ederim !! Bununla artık "tepki-div-100vh" gerekmez!
Andres Elizondo

1
en yararlı cevap!
Gauthier

@TammyTee haklı, orada tutmak daha iyi min-height: 100vh;çünkü aksi takdirde Firefox gibi tarayıcılarda kırılacak (en azından masaüstünde, iOS hangi tarayıcı olursa olsun webkit kullanıyor).
JoniVR

2
Bu çok güzel bir çözümdü, ancak iOS 13'te değişmiş gibi görünüyor - İlk bölümün altında ekstra alan görüyorum, ancak iOS 12.x için Safari'de tam olarak istendiği gibi çalışıyor. Codepen.io/RwwL/pen / PowjvPq (bunu çatallamak ve daha sonra ne demek istediğimi görmek için iOS'ta CodePen hata ayıklama modunda görüntülemek zorunda kalacaksınız).
RwwL

27

benim app böyle seviyorum (patlama ve iç içe postcss, böylece kodu buna göre değiştirin):

const appHeight = () => {
    const doc = document.documentElement
    doc.style.setProperty('--app-height', `${window.innerHeight}px`)
}
window.addEventListener('resize', appHeight)
appHeight()

css'nizde:

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

en azından krom mobil ve ipad üzerinde çalışır. Uygulamanız iOS'ta ana ekrana eklediğinizde ve yönlendirmeyi birkaç kez değiştirdiğinizde işe yaramaz; bir şekilde yakınlaştırma seviyeleri innerHeight değeriyle karışır, eğer bir çözüm bulursam bir güncelleme gönderebilirim.

gösteri


2
Bu aslında çok can sıkıcı bir soruna harika bir yaklaşım.
Michael Giovanni Pumo

1
"@Media'nın hepsi değil ve (hover: hover) {" ifadesinin mobil tarayıcıları tespit etmek için kurşun geçirmez bir yol olmadığını belirten bir uyarı eklemek istiyorum. Başka bir şey kullanmaktan çekinmeyin.
Andreas Herd

Bu yaklaşımı çok seviyorum. Yapacağım bir yorum, olay dinleyicisinin kullanımı hakkında. Bu, sayfanın yeniden boyanmasına neden olur ve yalnızca kullanıcının doğru görünümü (ör. Ana sayfa ilk görünümü) görmesi kesinlikle kritik olduğunda belirli senaryolarda kullanırım
Zach Gollwitzer

22

Oluşturduğum sitelerin çoğu için müşteri 100vh banner isteyecektir ve bulduğunuz gibi, kaydırmaya başladığınızda mobilde kötü bir "ürkek" deneyim ile sonuçlanır. Tüm cihazlarda sorunsuz ve tutarlı bir deneyim için sorunu şu şekilde çözerim:

İlk olarak banner öğesi CSS’mi height:100vh

Sonra banner öğemin piksel olarak yüksekliği almak ve bu yüksekliği kullanarak bir satır içi stil uygulamak için jQuery kullanın.

var viewportHeight = $('.banner').outerHeight();
$('.banner').css({ height: viewportHeight });

Bunu yapmak, sayfa yüklendiğinde mobil cihazlarda sorunu çözer, banner öğesi CSS kullanılarak 100vh olarak ayarlanır ve ardından jQuery, banner öğeme bir kullanıcı kaydırmaya başladığında yeniden boyutlandırılmasını engelleyen satır içi CSS yerleştirerek bunu geçersiz kılar.

Bununla birlikte, masaüstünde bir kullanıcı tarayıcı penceresini yeniden boyutlandırırsa, yukarıdaki jQuery nedeniyle artık piksel olarak ayarlanmış sabit bir yüksekliğe sahip olduğundan banner öğem yeniden boyutlandırılmaz. Bunu ele almak için belgemin gövdesine bir 'mobil' sınıf eklemek için Mobil Algılama'yı kullanıyorum . Ve sonra bir if ifadesinde yukarıdaki jQuery sarın:

if ($('body').hasClass('mobile')) {
  var viewportHeight = $('.banner').outerHeight();
  $('.banner').css({ height: viewportHeight });
}

Sonuç olarak, bir kullanıcı bir mobil cihazdaysa sayfamın gövdesinde 'mobile' sınıfı bulunur ve yukarıdaki jQuery yürütülür. Bu nedenle, banner öğem yalnızca mobil cihazlara satır içi CSS uygulanmasını sağlarken, bu arada masaüstünde orijinal 100vh CSS kuralı yerinde kalır.


4
Ben $('.banner').css({ height: window.innerHeight });bunun yerine, görünümün "gerçek" yüksekliği olan kullanmak için tweak olur . İnnerHeight'ın nasıl çalıştığına bir örnek
Martin

8
Bu, document.querySelector('.banner').style.height = window.innerHeight;gerçek JavaScript yazan kişiler içindir.
Fabian von Ellerts

18

Şu cevaba bakın: 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>


2
akıllı çözüm, mobil cihazlarda görünüm yüksekliği ile ilgili sorun
yaşıyordum

çok güzel bir çözüm. Sadece benim durumumda, ponyfill kullanmadım, daha ziyade 100vh kullandığım tüm masaüstü siteleri için mantıklıyken, mobil için var kullanıyorum (mobil dünyada IE11'imiz yok).
FrEaKmAn

Yalnızca iç içe elemanlar için çalışan çözüm. Başkasının birkaç yüz yerine geçmesi gerekiyorsa, (en azından çoğu zaman) regexp (-)? ([\ D.] +) Vh ile eşleşebilir ve bunu calc (var (- vh) *) ile değiştirebilirsiniz. 1 $ 2)
ecc521


6

Birkaç gün bir çözüm ararken, VuetJS'i Vuetify ile kullanan herkes için benim çözümüm (benim çözümüm v-app-bar, v-navigation-drawer ve v-footer kullanıyor): App.scss (App. vue) aşağıdaki içeriğe sahip:

.v-application {
    height: 100vh;
    height: -webkit-fill-available;
}

.v-application--wrap {
    min-height: 100vh !important;
    min-height: -webkit-fill-available !important;
}


1
Bu iyi çalışıyor ve Vue / Vuetify dünyasının dışında genelleştirilebilir.
leo

5

Benim için böyle bir iş yaptı:

height: calc(100vh - calc(100vh - 100%))

Yükseklikten farklı mı:% 100?
FF_Dev

Evet, 100vh yalnızca% 100 yalnızca kullanılabilir tüm üst alanı doldurduğunda (ana blok örneğin 50 piksel yüksekliğe sahip olabilir ve yalnızca bu üst yüksekliğe kadar doldurulacaktır), görünüm yüksekliğinin% 100'üdür (cihazınız). Kısacası.
Patryk Janik

4

@nils bunu açıkça açıkladı.

Sırada ne var?

CSS'de göreceli 'klasik' %(yüzde) kullanmaya geri döndüm .

Genellikle bir şeyi kullanmaktan daha fazla çaba sarf eder vh, ancak en azından garip UI aksaklıkları olmadan farklı cihazlarda ve tarayıcılarda çalışan oldukça kararlı bir çözümünüz var.


1
Yükseklik: Bannerlar için% 100 hala mobil tarayıcılarda atlıyor. Android'de test ediyorum ve şimdiye kadar Chrome ve Opera Mini, görünür VP yüksekliği olarak% 100 veriyor ve kaydırmada değişmiyor. Edge ve Firefox% 100 yüksekliği değiştirir ve görünümü yeniden boyar. Firefox, yırtılma, metin yeniden yazılmış, çok açık bir şekilde yeniden düzenlenmiş, özellikle kötü
Drenai

1
@Drenai bunu doğru bir şekilde uyguladığınızdan emin misiniz? Bunu jsfiddle.net üzerinde küçük bir örnek üzerinde kanıtlayabilir misiniz?
klimat

Evet, eminim :-)
Drenai

3

İPhone ve iPad'lerde bu sorunu yaşadığım bir web uygulaması buldum ve belirli Apple cihazlarını hedefleyen medya sorgularını kullanarak çözmeyi öneren bir makale buldum.

Bu makaledeki kodu paylaşıp paylaşamayacağımı bilmiyorum, ancak adres şu: http://webdesignerwall.com/tutorials/css-fix-for-ios-vh-unit-bug

Yazıyı alıntılamak: "iPhone ve iPad çözünürlüğünün eski sürümlerini hedefleyen medya sorgularını kullanarak öğe yüksekliğini cihaz yüksekliğiyle eşleştirin."

Tam yükseklik elemanlarını uyarlamak için sadece 6 medya sorgusu eklediler ve tamamen CSS uygulandığı için çalışmalıdır.

Düzenleme beklemede: Şu anda test edemiyorum, ancak geri dönüp sonuçlarımı bildireceğim.


23
hala bu sonuçları bekliyor 😉
gman

2
Söz verdiğim gibi geri gelmediğim için üzgünüm. Ama HTML ve CSS ile istediğimden daha uzun süre uğraştıktan sonra, düzenimin tasarımını değiştirdim ve ihtiyaçlarım için "tamam" olarak çalışan bir yol buldum, ancak evrensel bir çözüm değildi.
Jahaziel

2

Yeni olduğum için diğer cevaplar hakkında yorum yapamam.

Birisi bu işi yapmak için bir cevap arıyorsa (ve şu anda bu işi yapmak için gerekli göründüğü gibi javascript kullanabiliyorsa) bu yaklaşım benim için oldukça iyi çalıştı ve mobil yönelim değişikliğini de hesaba katıyor. Örnek kod için Jquery kullanın ama vanillaJS ile yapılabilir olmalıdır.

-İlk olarak, cihazın dokunup dokunmadığını veya üzerine gelip gelmediğini belirlemek için bir komut dosyası kullanıyorum. Çıplak kemik örneği:

if ("ontouchstart" in document.documentElement) {
    document.body.classList.add('touch-device');

} else {
    document.body.classList.add('hover-device');
}

Bu, daha sonra yükseklik komut dosyası için kullanılabilecek aygıt türüne (fareyle üzerine gelme veya dokunma) göre gövde öğesine sınıf ekler.

-Sonraki yük ve yön değiştirme sırasında cihazın yüksekliğini ayarlamak için bu kodu kullanın:

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


}

-Zaman aşımı, cihazın yön değişiminde yeni yüksekliği doğru hesaplayacağı şekilde ayarlanır. Zaman aşımı yoksa, tecrübelerime göre yükseklik doğru olmayacaktır. 500 ms aşırıya kaçabilir ama benim için çalıştı.

Tarayıcı CSS 100vh'yi geçersiz kılarsa, üzerine gelindiğinde cihazlarda -100vh bir yedek olur.


2
Touchstart tüm tarayıcılarda desteklenmez ve bazı mobil olmayan cihazlar o var developer.mozilla.org/en-US/docs/Web/Events/touchstart
Drenai

@Drenai Touchstart çoğu mobil tarayıcıda desteklenir. Masaüstünde destek biraz daha az, IE, Opera ve Safari desteklemiyor. Ancak asıl soru masaüstü değil mobil amaçlıdır. Bu da bunu geçerli bir cevap haline getiriyor.
Paul

Yorumlar için teşekkürler! Bu taktikleri esas olarak bazı mobil tarayıcılarda ekranın yeniden ayarlanması ve zıplamasının üstesinden gelmek için kullandım. Tarayıcı dokunmatik başlatmayı desteklemiyorsa, geri dönüş css 100vh olacaktır - 100vh desteklenmiyorsa bu farklı bir konudur. Masaüstü cihazının dokunmatik desteğe sahip olması durumunda, yükseklik javascript ile hesaplanacaktır. Daha sonra 100vh'nin sağladığı yeniden boyutlandırmada yeniden hesaplamayı kaybediyoruz, ancak masaüstünde yönlendirme değişiklikleri olmadığından genel olarak ölümcül bir sorun değil.
tjgoodman

Ayrıca, yükseklik hesaplaması da yeniden boyutlandırma olayına eklenebilir, ancak daha sonra mobil cihazlarda aynı düzeltme ve zıplama problemiyle karşılaşabiliriz. Bu nedenle, bu taktiklerin pratik olduğunu gördüm.
tjgoodman

1
@Paul Chrome ve Firefox masaüstü tarayıcılarında dokunma başlangıcı varsa, mutlaka bir mobil tarayıcı algılamak için kullanılacak yanlış özellik mi? Windows'ta Chrome ve Firefox'ta test ettim ve her ikisi de bu testi geçiyor
Drenai

2

Aşağıdaki kod sorunu çözdü (jQuery ile).

var vhHeight = $("body").height();
var chromeNavbarHeight = vhHeight - window.innerHeight;
$('body').css({ height: window.innerHeight, marginTop: chromeNavbarHeight });

Ve diğer elemanlar %yerine koymak için bir birim olarak kullanırlar vh.


2

İşte React uygulamam için kullandığım bir çalışma.

iPhone 11 Pro ve iPhone Pro Max - 120 piksel

iPhone 8 - 80 piksel

max-height: calc(100vh - 120px);

Bir uzlaşma ama nispeten basit bir düzeltme


1

Aşağıdakiler benim için çalıştı:

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

bodyGörünür görüntü alanı yüksekliği alacak ve #your-app-containerbirlikte height: 100%bu kapsayıcı görünür görüntü alanı yüksekliği almak yapacaktır.



0

Çünkü o sabit olmayacak, gibi bir şey yapabilirsiniz:

# html
<body>
  <div class="content">
    <!-- Your stuff here -->
  </div>
</body>

# css
.content {
  height: 80vh;
}

Benim için, birçok cihazda ve tarayıcıda çalışamayan JavaScript ile oynamaktan daha hızlı ve daha saf bir çözümdü.

vhİhtiyaçlarınıza uygun değeri kullanın .


0

Mobil cihazlarda vh kullanmak, herhangi bir adres çubuğu vb. İçermeyen cihazın tüm yüksekliğini kullanan tasarım seçimleri nedeniyle 100vh ile çalışmaz.

Gerçek görünüm yüksekliği ile orantılı div yükseklikleri içeren bir düzen arıyorsanız, aşağıdaki saf css çözümünü kullanıyorum:

:root {
  --devHeight: 86vh; //*This value changes
}

.div{
    height: calc(var(--devHeight)*0.10); //change multiplier to suit required height
}

Görünüm yüksekliğini ayarlamak için iki seçeneğiniz vardır, --devHeight değerini çalışan bir yüksekliğe manuel olarak ayarlayın (ancak kodladığınız her cihaz türü için bu değeri girmeniz gerekir)

veya

Pencere yüksekliğini almak için javascript'i kullanın ve ardından görünüm penceresini yüklemek ve yenilemek için --devheight'ı güncelleyin (ancak bu javascript kullanımını gerektirir ve saf bir css çözümü değildir)

Doğru görüntüleme yüksekliğinizi elde ettikten sonra, yüksekliği atadığınız her bir bölmedeki çarpanı değiştirerek toplam görüntüleme alanı yüksekliğinin tam yüzdesinde birden fazla div oluşturabilirsiniz.

0.10 = görüş yüksekliğinin% 10'u 0.57 = görüş yüksekliğinin% 57'si

Umarım bu birine yardımcı olabilir;)


1
Güzel bir çözüm. Bununla ilgili daha fazla bilgiyi şurada bulabilirsiniz: Css-tricks bu makalede.
Amaury Hanser

0

Aşağıdaki komut dosyasını ve stilini ekleyerek bunu yapabilirsiniz

  function appHeight() {
    const doc = document.documentElement
    doc.style.setProperty('--vh', (window.innerHeight*.01) + 'px');
  }
  window.addEventListener('resize', appHeight);
  appHeight();

stil

.module {
 height: 100vh; /* Fallback for browsers that do not support Custom Properties */
  height: calc(var(--vh, 1vh) * 100);
}

0

html, body { height: 100% }100vh'nin mobil cihazlar üzerindeki etkisine yönelik bir şey deneyin .


-1

position: fixed; top: 0; bottom: 0;Kapsayıcıya özellikler vermeyi deneyebilirsiniz .


2
Bunun neden soruya bir cevap olduğu hakkında daha fazla bilgi ekleyin.
Enfekte Drake
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.