Obraz tła przeskakuje, gdy pasek adresu ukrywa iOS / Android / Mobile Chrome

174

Obecnie rozwijam responsywną witrynę przy użyciu Twitter Bootstrap.

Witryna ma pełnoekranowy obraz tła na telefonie komórkowym / tablecie / komputerze. Te obrazy obracają się i zanikają, używając dwóch elementów div.

Jest prawie doskonały, z wyjątkiem jednego problemu. Korzystając z iOS Safari, przeglądarki Android lub Chrome na Androida, tło nieznacznie podskakuje, gdy użytkownik przewinie stronę w dół i powoduje ukrycie paska adresu.

Strona jest tutaj: http://lt2.daveclarke.me/

Odwiedź go na urządzeniu mobilnym i przewiń w dół, a powinieneś zobaczyć zmianę rozmiaru / przesunięcie obrazu.

Kod, którego używam dla DIV w tle, jest następujący:

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

Wszystkie sugestie są mile widziane - to już od jakiegoś czasu przykuwa mi uwagę !!

Dave Clarke
źródło
Twój link wymaga autoryzacji ... także, pokaż nam trochę kodu!
Shawn Taylor,
Nowy link dodany i pokazany kod dla pozycjonowania w tle itp.
Dave Clarke
1
Jeśli masz ten problem, możesz sprawdzić developers.google.com/web/updates/2016/12/url-bar-resizing . Ten problem (w pewnym sensie) został już rozwiązany, ale nadal dotyczy elementów, które już tak position: fixed.
Adam Reis
@AdamReis Wreszcie! Dzięki za wysłanie wiadomości
Dave Clarke

Odpowiedzi:

106

Ten problem jest spowodowany zmniejszaniem się / przesuwaniem pasków adresu URL oraz zmianą rozmiaru elementów div # bg1 i # bg2, ponieważ mają one 100% wysokości i są „ustalone”. Ponieważ obraz tła jest ustawiony jako „okładka”, dostosuje rozmiar / położenie obrazu, ponieważ obszar zawierający jest większy.

W oparciu o responsywny charakter witryny tło musi się skalować. Rozważam dwa możliwe rozwiązania:

1) Ustaw wysokość # bg1, # bg2 na 100vh. W teorii to eleganckie rozwiązanie. Jednak iOS ma błąd vh ( http://thatemil.com/blog/2013/06/13/viewport-relative-unit-strangeness-in-ios-6/ ). Próbowałem użyć maksymalnej wysokości, aby zapobiec problemowi, ale pozostał.

2) Pasek adresu URL nie wpływa na rozmiar widocznego obszaru, który jest określany przez JavaScript. Dlatego JavaScript może być użyty do ustawienia statycznej wysokości na # bg1 i # bg2 na podstawie rozmiaru widocznego obszaru. Nie jest to najlepsze rozwiązanie, ponieważ nie jest to czysty CSS i podczas ładowania strony występuje niewielki skok obrazu. Jest to jednak jedyne realne rozwiązanie, które widzę, biorąc pod uwagę błędy „vh” iOS (które nie wydają się być naprawione w iOS 7).

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

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

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

Na marginesie, widziałem wiele problemów z tymi paskami adresu URL w systemie iOS i Android. Rozumiem cel, ale naprawdę muszą przemyśleć dziwną funkcjonalność i spustoszenie, jakie wprowadzają na stronach internetowych. Najnowsza zmiana polega na tym, że nie można już „ukrywać” paska adresu URL podczas ładowania strony w systemie iOS lub Chrome za pomocą sztuczek przewijania.

EDYCJA: Chociaż powyższy skrypt działa doskonale, aby zapobiec zmianie rozmiaru tła, powoduje zauważalną lukę, gdy użytkownicy przewijają w dół. Dzieje się tak, ponieważ utrzymuje rozmiar tła na 100% wysokości ekranu bez paska adresu URL. Jeśli dodamy do wysokości 60 pikseli, jak sugeruje szwajcarski, problem znika. Oznacza to, że nie widzimy dolnych 60 pikseli obrazu tła, gdy obecny jest pasek adresu URL, ale uniemożliwia to użytkownikom zobaczenie luki.

function resizeBackground() {
    bg.height( $(window).height() + 60);
}
Jason
źródło
Dzięki za to. Jutro zawiruję i dam znać, jak sobie radzę :)
Dave Clarke
5
To jest cudowne. Zaimplementowałem Twoje drugie rozwiązanie, które działało prawie idealnie z zaledwie kilkoma pikselami odstępu między stopką a obrazem tła. Zmieniłem Twój czwarty wiersz kodu na: bg.height(jQuery(window).height() + 60);który działa pięknie na wszystkich moich urządzeniach! Dzięki :)
Dave Clarke
6
błąd vh w iOS został naprawiony w iOS8, ale problem z Androidem już nie. Używam vhjednostek i oczywiście 100vhjest większy, gdy pasek adresu jest ukryty. To głupie, że ten skok następuje po zatrzymaniu przewijania. Po prostu wygląda na wadliwego. Skończyło się na tym, że użyłem przejścia na wysokości, aby wyglądało na zamierzone.
ProblemsOfSumit
1
Udało mi się rozwiązać ten problem, przenosząc tło z bodyotoki <div>zawijającej całą zawartość strony. Brak skaczących środowisk na iOS lub Androidzie!
Marius Schulz,
2
Rozwiązanie JS nie działa dla mnie (Android). Potwierdzono, że skrypt ustawia wysokość, ale problem nadal występuje.
jwinn
61

Okazało się, że odpowiedź Jasona nie do końca mi odpowiada i wciąż dostaję skoku. Javascript zapewniał, że nie było przerwy na górze strony, ale tło wciąż podskakiwało, gdy pasek adresu znikał / pojawiał się ponownie. Więc oprócz poprawki JavaScript zastosowałem transition: height 999999ssię do div. Tworzy to przejście o tak długim czasie trwania, że ​​praktycznie zamraża element.

AlexKempton
źródło
23
Zasługujesz na +1 za prawdziwe nieszablonowe myślenie. Niestety uniemożliwia to dostosowanie rozmiaru div do wszelkich zmian rozmiaru ekranu, w tym na przykład spowodowanych obrotem ekranu.
tobik
+1 za kreatywność! Może być konieczne użycie tego na razie, ponieważ problem jest złożony, jeśli używasz vwlub vhdo ustawiania rozmiaru czcionki w tym kontenerze nadrzędnym.
robabby
6
@tobik Nadal można zmniejszyć skok spowodowany zmianą
widocznego obszaru, ustawiając
7
spróbuj teraz obrócić telefon
cuddlecheek
1
@tobik to właściwie sprawia, że ​​jest to bardziej funkcja niż błąd;) dobre myślenie
dimitrieh
23

Mam podobny problem w nagłówku naszej witryny.

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

Spowoduje to gwałtowne przewijanie w przeglądarce Chrome na Androida, ponieważ .header-container zostanie przeskalowany po ukryciu paska adresu URL i usunięciu palca z ekranu.

Rozwiązanie CSS:

Dodanie następujących dwóch wierszy zapobiegnie ukryciu paska adresu URL i możliwości przewijania w pionie:

html {
    overflow: hidden;
}
body {
    overflow-y: scroll;
    -webkit-overflow-scrolling:touch;
}
mata
źródło
4
Tak, to rozwiązuje problem tak, jak mówisz, ale do bani jest to, że pasek nawigacji jest zawsze wyświetlany. Na niektórych telefonach może to zająć trochę cennego miejsca na ekranie!
Dave Clarke
1
To prawda, aby temu zapobiec, możesz dodatkowo użyć obejścia JavaScript. Ale ten przykład działa w ogóle bez JS.
mata
3
Gdy wypróbowałem to rozwiązanie, przewijanie jest całkowicie wyłączone.
Nithin Baby
1
Dzięki, to działało świetnie w mojej sytuacji! Powinienem wspomnieć dla każdego, kto mógłby to przegapić, że tagi HTML i body muszą być ustawione na 100% wysokości, aby to zadziałało (początkowo tylko przejrzałem twoją odpowiedź na początku i przeskoczyłem do pierwszej wzmianki o „rozwiązaniu”).
gburning
-webkit-overflow-scrolling nie powinno być używane w witrynach produkcyjnych. developer.mozilla.org/en-US/docs/Web/CSS/…
Fredrik Westerlund,
16

Problem można rozwiązać za pomocą zapytania o media i trochę matematyki. Oto rozwiązanie dla orientacji portretowej:

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

Ponieważ vh zmieni się, gdy pasek adresu URL zniknie, musisz określić wysokość w inny sposób. Na szczęście szerokość widocznego obszaru jest stała, a urządzenia mobilne mają tylko kilka różnych współczynników proporcji; jeśli możesz określić szerokość i proporcje, trochę matematyki da ci wysokość rzutni dokładnie tak, jak powinna działać . Oto proces

1) Utwórz serię zapytań o media dla współczynników proporcji, na które chcesz kierować reklamy.

  • użyj współczynnika proporcji urządzenia zamiast współczynnika proporcji, ponieważ ten ostatni zmieni rozmiar, gdy zniknie pasek adresu URL

  • Dodałem „maksymalny” do współczynnika proporcji urządzenia, aby kierować reklamy na dowolne proporcje, które zdarzają się występować pomiędzy najpopularniejszymi. Nie będą tak precyzyjne, ale będą dostępne tylko dla mniejszości użytkowników i nadal będą dość zbliżone do właściwego vh.

  • zapamiętaj zapytanie o media, używając opcji poziomej / pionowej, więc w przypadku portait musisz odwrócić liczby

2) dla każdego zapytania o media pomnóż dowolny procent wysokości w pionie, w jakim ma znajdować się element, przez odwrotność współczynnika proporcji.

  • Ponieważ znasz szerokość i stosunek szerokości do wysokości, po prostu pomnóż żądany% (w twoim przypadku 100%) przez stosunek wysokości do szerokości.

3) Musisz określić wysokość paska adresu URL, a następnie odjąć ją od wysokości. Nie znalazłem dokładnych pomiarów, ale używam 9% dla urządzeń mobilnych w krajobrazie i wydaje się, że działa całkiem dobrze.

To nie jest zbyt eleganckie rozwiązanie, ale inne opcje też nie są zbyt dobre, biorąc pod uwagę:

  • Twoja witryna wydaje się być wadliwa dla użytkownika,

  • posiadające elementy o nieodpowiednich wymiarach, lub

  • Używanie javascript do podstawowych stylizacji,

Wadą jest to, że niektóre urządzenia mogą mieć inne wysokości paska adresu URL lub współczynniki proporcji niż najpopularniejsze. Jednak używanie tej metody, jeśli tylko niewielka liczba urządzeń cierpi na dodawanie / odejmowanie kilku pikseli, wydaje mi się o wiele lepsze niż każdy, kto ma rozmiar strony internetowej podczas przesuwania.

Aby było to łatwiejsze, stworzyłem również mixin SASS:

@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
źródło
2
Bardzo kreatywne! Jednak nie jest fanem przypuszczeń 9%.
w00t
1
Bardzo proste i sprytne! Możesz dodać parametr do vh-fix, aby zasymulować oryginalne zachowanie: @mixin vh-fix($vh: 100)=>height: calc(100vw * (1.333 * $vh / 100) - 9%)
mjsarfatti
1
Powyższe powinno być:height: calc(100vw * (1.333 * #{$vh} / 100) - 9%)
mjsarfatti
W moim przypadku zadziałało to naprawdę dobrze, a nawet lepiej po usunięciu -9%.
Ben Fleming
12

Wszystkie odpowiedzi tutaj używają windowwysokości, na którą ma wpływ pasek adresu URL. Czy wszyscy zapomnieli o screenwzroście?

Oto moje rozwiązanie jQuery:

$(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);
  }
});

Dodawanie .css() części zmienia nieuchronnie wyrównany do góry element pozycjonowany bezwzględnie na wyrównany do dołu, więc nie ma żadnego przeskoku. Chociaż przypuszczam, że nie ma powodu, aby nie dodawać tego bezpośrednio do normalnego CSS.

Potrzebujemy sniffera klienta użytkownika, ponieważ wysokość ekranu na komputerach stacjonarnych nie byłaby pomocna.

To wszystko jest założeniem #background jest to element o stałej pozycji wypełniający okno.

Dla purystów JavaScript (ostrzeżenie - nieprzetestowane):

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

EDYCJA: Przepraszamy, ale to nie rozwiązuje bezpośrednio twojego problemu z więcej niż jednym tłem. Jest to jednak jeden z pierwszych wyników wyszukiwania tego problemu związanego ze skokami tła na urządzeniach mobilnych.

cr0ybot
źródło
2
Wypróbowałem milion takich odpowiedzi i jest to zdecydowanie najlepsza. Początkowo próbowałem użyć tego na <body>, ponieważ miało to tło. Używanie elementu div do zawijania całej strony powodowało inne problemy. Użycie pustego div z indeksem z: -1 jako tła wydawało się najlepszym rozwiązaniem w połączeniu z powyższym. Usunąłem wykrywanie urządzeń mobilnych, ponieważ zrobienie tego na komputerze stacjonarnym nie zaszkodzi mojej witrynie. Brak matematyki (która może nieprawidłowo odgadnąć rozmiar zakładek), brak obsługi potrzebnej do zmiany rozmiaru. Tło to tylko cały ekran, zakotwiczony u dołu. Gotowe. Kocham to!
Evan Langlois
9

Natknąłem się również na ten problem, gdy próbowałem stworzyć ekran wejściowy, który obejmowałby cały widok. Niestety zaakceptowana odpowiedź już nie działa.

1) Elementy o wysokości ustawionej na 100vh zmianę rozmiaru za każdym razem, gdy zmienia się rozmiar rzutni, w tym w przypadkach, gdy jest to spowodowane (z) wyświetlaniem paska adresu URL.

2) $(window).height()zwraca wartości, na które ma również wpływ rozmiar paska adresu URL.

Jednym z rozwiązań jest „zamrożenie” elementu za pomocą, transition: height 999999sjak sugeruje odpowiedź AlexKempton . Wadą jest to, że skutecznie wyłącza adaptację do wszystkich zmian rozmiaru rzutni, w tym tych spowodowanych obrotem ekranu.

Więc moim rozwiązaniem jest ręczne zarządzanie zmianami widocznego obszaru za pomocą JavaScript. To pozwala mi zignorować małe zmiany, które mogą być spowodowane przez pasek adresu URL i reagować tylko na duże.

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

EDYCJA: Właściwie używam tej techniki razem z height: 100vh. Strona jest renderowana poprawnie od samego początku, a następnie włącza się javascript i zaczyna ręcznie zarządzać wysokością. W ten sposób nie ma żadnego migotania podczas ładowania strony (a nawet później).

tobik
źródło
1
Użyłem czegoś podobnego, ale zamiast ustawiać height: 100vhw początkowym CSS, ustawiam, min-height:100vha następnie przy zmianie rozmiaru okna obliczam min-heighti ustawiam go na wysokość portu widoku. Jest to przydatne, gdy witryna jest wyświetlana na małych ekranach, a zawartość jest zbyt duża, aby zmieścić się w widocznym obszarze. Ustawienie debounce / throttle Timeout na zdarzeniu zmiany rozmiaru pomaga poprawić wydajność w niektórych przeglądarkach (zmiana rozmiaru zwykle uruchamia się bardzo często)
Troy Morehouse,
Myślę, że w pewnym momencie próbowałem też użyć min-heightzamiast tego, ale potem napotykam problem, gdy musiałem wyśrodkować wewnętrzną zawartość w pionie. W jakiś sposób centrowanie w pionie może być trudne, gdy element zewnętrzny jest heightustawiony na auto. Więc wymyśliłem stałą minimalną wysokość, która powinna wystarczyć do umieszczenia dowolnej możliwej treści i ustawiłem ją w początkowym CSS. Ponieważ min-heightma wyższy priorytet niż height, działa całkiem dobrze.
tobik
Ach tak, miałem ten sam problem, ale naprawiłem to przez zmianę jumbotron się display: table, a następnie ustawienie pojemnika wewnętrznego display: table-cellz vertical-align: middle. Działał jak urok.
Troy Morehouse
Naprawdę? Ponieważ próbowałem tego samego podejścia, ale nie udało mi się. Naprawdę nie pamiętam, w czym był problem, ale może to mieć znaczenie: stackoverflow.com/questions/7790222/…
tobik
Upewnij się tylko, że unikasz procentowego wypełnienia lub marginesów. Spowodował kilka dziwnych problemów z renderowaniem w IE8, chociaż nowoczesne przeglądarki były w porządku.
Troy Morehouse,
8

Rozwiązanie obecnie używam jest do sprawdzenia userAgentna $(document).readycelu sprawdzenia, czy jest to jeden z przestępstwa przeglądarek. Jeśli tak, wykonaj następujące kroki:

  1. Ustaw odpowiednie wysokości na aktualną wysokość rzutni zamiast „100%”
  2. Zapisz bieżącą wartość poziomą rzutni
  3. Następnie, po włączeniu $(window).resize, zaktualizuj tylko odpowiednie wartości wysokości, jeśli nowy wymiar poziomej rzutni różni się od jego wartości początkowej
  4. Zapisz nowe wartości poziome i pionowe

Opcjonalnie możesz również przetestować zezwalanie na zmiany rozmiaru w pionie tylko wtedy, gdy są one poza wysokością pasków adresu.

Aha, i pasek adresu ma wpływ $(window).height. Zobacz: Zmiana paska adresu przeglądarki Mobile Webkit (chrome) $ (window) .height (); Dokonywanie rozmiaru tła: zmiana skali okładki za każdym razem JS „Okno” szerokość-wysokość a „ekran” szerokość-wysokość?

poseł
źródło
Nie próbowałem tego, ale czy Twój pierwszy punkt nie działałby na iOS? ( thatemil.com/blog/2013/06/13/… )
Dave Clarke,
Naprawiałem jego wartość w pierwszym kroku, ale jestem zaskoczony, że znalazłeś odpowiedź Jasona, aby rozwiązać problem. Jak zauważyłem, wraz z innym użytkownikiem we wcześniejszym pytaniu, które połączyłem, okazało się, że wartość metody $ (window) .height () ZMIENIA SIĘ, gdy pasek adresu w chrome na Androidzie jest lub nie jest widoczny. Zrzuciłem razem tę małą stronę, która po prostu ujawnia $ (window) .height () powoduje alert i zdecydowanie zapewnia różne wartości na moim Nexusie 4 w chrome, gdy pasek adresu jest / nie jest widoczny: stormy-meadow-5908 .herokuapp.com
mp
To w 100% rozwiązuje problem na moim urządzeniu z Androidem, chociaż widzę podobny problem na moim iPadzie, którego to nie wydaje się naprawiać, a wciąż się zastanawiam.
Dave Clarke,
Czy możesz podać kod swojego rozwiązania, a ja go wypróbuję?
Dave Clarke,
4

Znalazłem naprawdę proste rozwiązanie bez użycia Javascript:

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

Wszystko to opóźnia ruch, tak że jest niewiarygodnie wolny, że nie jest zauważalny.

Pav Sidhu
źródło
@ Tyguy7 to działa dobrze, gdy swoją wysokość nie jest ustawiony na stałą wartość, to znaczy 100%, 100vh. IE8 to jedyna duża przeglądarka, która nie obsługuje przejść.
Pav Sidhu
Świetne i proste rozwiązanie!
zdarsky.peter
3
Działa to świetnie, dopóki nie jesteś na urządzeniu, na którym możesz zmienić tryb z pionowego na poziomy. Kiedy tak się dzieje, projekt jest zrujnowany.
Nagy Nick,
@NagyNick to nie był dla mnie taki duży problem. Możesz wykryć zmianę orientacji w JavaScript i dostosować obraz tła.
Pav Sidhu,
3

Moje rozwiązanie wymagało trochę javascript. Zachowaj 100% lub 100 vh w elemencie div (pozwoli to uniknąć wyświetlania elementu div podczas początkowego ładowania strony). Następnie, gdy strona się załaduje, chwyć wysokość okna i zastosuj ją do danego elementu. Unika skoku, ponieważ teraz masz statyczną wysokość swojego div.

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

$hero.css('height', h);
Todd Miller
źródło
3

Stworzyłem waniliowe rozwiązanie javascript do korzystania z jednostek VH. Używanie VH praktycznie wszędzie odbywa się poprzez paski adresu minimalizujące przewijanie. Aby naprawić błąd, który wyświetla się podczas przerysowywania strony, mam tutaj ten plik js, który pobierze wszystkie elementy za pomocą jednostek VH (jeśli nadasz im klasę .vh-fix) i nada im wbudowane wysokości pikseli. Zasadniczo zamrażanie ich na żądanej wysokości. Możesz to zrobić podczas obracania lub zmiany rozmiaru widocznego obszaru, aby zachować responsywność.

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'
  }
}

To rozwiązało wszystkie moje przypadki użycia, mam nadzieję, że pomoże.

Geek Devigner
źródło
3

to jest moje rozwiązanie, aby rozwiązać ten problem, dodałem komentarze bezpośrednio do kodu. Przetestowałem to rozwiązanie i działa dobrze. Mam nadzieję, że będziemy przydatni, ponieważ każdy ma ten sam problem.

//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
źródło
1
Wywołujesz metodę setHeight () wewnątrz metody changeHeight, jeśli zapytanie pasuje, a także jeśli nie pasuje. Po prostu usuń instrukcję if, ponieważ nie jest to konieczne.
Dennis Meissner
2

To najlepsze rozwiązanie (najprostsze) ponad wszystko, czego próbowałem.

... I to nie zachowuje natywnego wyglądu paska adresu !

Możesz na przykład ustawić wysokość w CSS na 100%, a następnie ustawić wysokość na 0,9 * wysokości okna w pikselach za pomocą javascript, kiedy dokument jest ładowany.

Na przykład z jQuery:

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

)

Niestety nie ma niczego, co działa z czystym CSS: P, ale jest też minimalne vhi vwzawiera błędy na iPhone'ach - użyj procentów.


źródło
1

Ustawiłem element szerokości za pomocą javascript. Po ustawieniu de vh.

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

To działa dla mnie. Nie używam jquery ect. ponieważ chcę, aby ładował się tak szybko, jak to możliwe.

Johan Hoeksma
źródło
1

Zrozumienie wszystkich szczegółów tego problemu i znalezienie najlepszej implementacji zajęło kilka godzin. Okazuje się, że od kwietnia 2016 r. Tylko iOS Chrome ma ten problem. Próbowałem na Androidzie Chrome i iOS Safari - oba były w porządku bez tej poprawki. Więc poprawka dla iOS Chrome, której używam, to:

$(document).ready(function() {
   var screenHeight = $(window).height();
   $('div-with-background-image').css('height', screenHeight + 'px');
});
littlequest
źródło
1

Prosta odpowiedź, jeśli pozwala na to twoje tło, dlaczego nie ustawić rozmiaru tła: na coś, co obejmuje tylko szerokość urządzenia za pomocą zapytań o media i użyj obok: po pozycji: naprawiono; siekać tutaj .

IE: background-size: 901px; dla dowolnych ekranów <900px? Nie jest doskonały ani responsywny, ale zadziałał dla mnie urokiem na telefonie komórkowym <480px, ponieważ używam abstrakcyjnego BG.

EasterMedia
źródło
0

Używam tego obejścia: Napraw wysokość bg1 podczas ładowania strony przez:

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

Następnie dołącz detektor zdarzenia zmiany rozmiaru do okna, który robi to: jeśli różnica wysokości po zmianie rozmiaru jest mniejsza niż 60 pikseli (cokolwiek więcej niż wysokość paska adresu URL), nie rób nic, a jeśli jest większa niż 60 pikseli, ustaw ponownie wysokość bg1 na wysokość jego rodzica! pełny kod:

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: Ten błąd jest tak irytujący!

AadityaTaparia
źródło
0

Podobna do odpowiedzi @AlexKempton. (przepraszam, nie mogę komentować)

Używałem długich opóźnień przejścia, aby zapobiec zmianie rozmiaru elementu.

na przykład:

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

Wadą jest to, że zapobiega zmianie rozmiaru elementu, w tym przy obracaniu urządzenia, jednak możesz użyć niektórych JS do wykrycia orientationchangei zresetowania wysokości, jeśli był to problem.

Chris Anderson
źródło
0

Dla tych, którzy chcieliby posłuchać rzeczywistej wysokości wewnętrznej i przewijania w pionie okna, podczas gdy przeglądarka mobilna Chrome zmienia pasek adresu URL z pokazanego na ukryty i odwrotnie, jedynym rozwiązaniem, które znalazłem, jest ustawienie funkcji interwału i zmierzyć rozbieżność wartości window.innerHeightz poprzednią wartością.

To wprowadza ten kod:

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

Mam nadzieję, że to się przyda. Czy ktoś zna lepsze rozwiązanie?

Édouard Mercier
źródło
0

Rozwiązaniem, które wymyśliłem, mając podobny problem, było ustawienie wysokości elementu przy window.innerHeightkażdym uruchomieniu touchmovezdarzenia.

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

To sprawia, że ​​element obejmuje zawsze dokładnie 100% dostępnego ekranu, ni mniej, ni więcej. Nawet podczas ukrywania lub pokazywania paska adresu.

Niemniej jednak szkoda, że ​​musimy wymyślać takie łatki, w których proste position: fixedpowinny działać.

Paweł
źródło
0

Dzięki obsłudze niestandardowych właściwości CSS (zmiennych) w iOS możesz je ustawić za pomocą JS i używać ich tylko na iOS.

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
źródło
0

Moja odpowiedź jest dla każdego, kto tu przychodzi (tak jak ja), aby znaleźć odpowiedź na błąd spowodowany ukrywaniem adresu gołego / interfejsu przeglądarki.

Ukrywanie paska adresu powoduje wyzwolenie zdarzenia zmiany rozmiaru. Ale inaczej niż w przypadku innych zdarzeń zmiany rozmiaru, takich jak przejście do trybu poziomego, nie zmienia to szerokości okna. Więc moim rozwiązaniem jest podłączenie się do zdarzenia resize i sprawdzenie, czy szerokość jest taka sama.

// 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.
źródło