Фоновые изображения перескакивают, когда адресная строка скрывает iOS / Android / мобильный Chrome

В настоящее время я разрабатываю отзывчивый сайт, используя Twitter Bootstrap.

На сайте есть полноэкранное фоновое изображение на мобильном телефоне / планшете / на рабочем столе. Эти изображения вращаются и исчезают через каждый, используя два div.

Это почти идеально, за исключением одной проблемы. Используя iOS Safari, Android Browser или Chrome на Android, фон слегка перескакивает, когда пользователь прокручивает страницу вниз и вызывает скрытие адресной строки.

Сайт находится здесь: http://lt2.daveclarke.me/

Посетите его на мобильном устройстве и прокрутите вниз, и вы должны увидеть изменение размера изображения / перемещение.

Код, который я использую для фона DIV, выглядит следующим образом:

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

Все предложения приветствуются – это немного помогло мне!

Solutions Collecting From Web of "Фоновые изображения перескакивают, когда адресная строка скрывает iOS / Android / мобильный Chrome"

Эта проблема возникает из-за того, что полосы URL сокращаются / сползают в сторону и меняют размер разделов # bg1 и # bg2, так как они 100% высотой и «фиксированы». Поскольку фоновое изображение настроено на «обложка», оно будет регулировать размер / положение изображения по мере того, как область содержимого больше.

Основываясь на отзывчивом характере сайта, фон должен масштабироваться. Я принимаю два возможных решения:

1) Установите для # bg1, # bg2 height значение 100vh. Теоретически это элегантное решение. Однако у iOS есть ошибка vh ( http://thatemil.com/blog/2013/06/13/viewport-relative-unit-strangeness-in-ios-6/ ). Я попытался использовать максимальную высоту, чтобы предотвратить проблему, но она осталась.

2) Размер видового экрана, определяемый Javascript, не зависит от строки URL. Поэтому Javascript можно использовать для установки статической высоты на # bg1 и # bg2 на основе размера видового экрана. Это не лучшее решение, так как это не чистый CSS, и есть небольшой скачок изображения при загрузке страницы. Тем не менее, это единственное жизнеспособное решение, которое я вижу, рассматривая ошибки iOS «vh» (которые, как представляется, не исправлены в iOS 7).

 var bg = $("#bg1, #bg2"); function resizeBackground() { bg.height($(window).height()); } $(window).resize(resizeBackground); resizeBackground(); 

На стороне примечания, я видел так много проблем с этими размерами баров URL в iOS и Android. Я понимаю цель, но им действительно нужно продумать странную функциональность и хаос, которые они приносят на веб-сайты. Последнее изменение: вы больше не можете «скрывать» строку URL-адреса при загрузке страницы на iOS или Chrome с помощью прокрутки.

EDIT: Несмотря на то, что вышеприведенный скрипт отлично работает для сохранения фона при изменении размера, он вызывает заметный разрыв, когда пользователи прокручиваются вниз. Это связано с тем, что он сохраняет фоновый размер на 100% от высоты экрана за вычетом строки URL. Если мы добавим 60 пикселей на высоту, как предполагает швейцар, эта проблема исчезнет. Это означает, что мы не увидим нижний 60px фонового изображения, когда панель URL присутствует, но она не позволяет пользователям видеть разрыв.

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

Я обнаружил, что ответ Джейсона не подходит для меня, и я все еще получаю прыжок. Javascript обеспечил отсутствие пробела в верхней части страницы, но фон все еще прыгал, когда адресная строка исчезла / снова появилась. Итак, как и исправление Javascript, я применил transition: height 999999s к div. Это создает переход с продолжительностью до тех пор, пока он практически не заморозит элемент.

У меня такая же проблема в заголовке нашего сайта.

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

Это закончится скачкообразным прокруткой на андроидном хроме, потому что контейнер .header будет масштабироваться после того, как скрыта строка url-bar, и палец будет удален с экрана.

CSS-решение:

Добавление следующих двух строк позволит предотвратить скрытие скрытых ссылок и вертикальной прокрутки:

 html { overflow: hidden; } body { overflow-y: scroll; -webkit-overflow-scrolling:touch; } 

Проблема может быть решена с помощью медиа-запроса и некоторой математики. Вот решение для ориентации portait:

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

Так как vh изменится, когда строка url исчезнет, ​​вам нужно определить высоту другим способом. К счастью, ширина окна просмотра постоянна, а мобильные устройства входят в несколько разных пропорций; Если вы можете определить ширину и соотношение сторон, небольшая математика даст вам высоту видового экрана точно так же, как и vh. Вот процесс

1) Создайте серию медиа-запросов для пропорций, которые вы хотите настроить.

  • Используйте соотношение сторон устройства и пропорции, поскольку последний будет изменять размер, когда полоса url исчезнет

  • Я добавил «max» к соотношению сторон устройства к цели любого соотношения сторон, которое происходит между самыми популярными. Это будет не так точно, но они будут только для меньшинства пользователей и все равно будут близки к правильному vh.

  • Помните медиа-запрос, используя горизонтальный / вертикальный, так что для portait вам нужно перевернуть числа

2) для каждого мультимедийного запроса умножайте любой процент вертикальной высоты, который вы хотите, чтобы элемент находился в vw по обратному отношению к формату.

  • Поскольку вы знаете ширину и отношение ширины к высоте, вы просто умножаете% вы хотите (100% в вашем случае) на отношение высоты / ширины.

3) Вы должны определить высоту строки url, а затем минус это с высоты. Я не нашел точных измерений, но я использую 9% для мобильных устройств в ландшафте и, похоже, работает достаточно хорошо.

Это не очень изящное решение, но другие варианты тоже не очень хорошие, учитывая, что они:

  • Если ваш веб-сайт выглядит ошибкой для пользователя,

  • С неправильным размером элементов или

  • Используя javascript для базового стиля,

Недостатком является то, что некоторые устройства могут иметь разную высоту полосы или соотношение сторон, чем самые популярные. Однако, используя этот метод, если только небольшое количество устройств страдает добавлением / вычитанием нескольких пикселей, это кажется мне намного лучше, чем все, у кого есть изменение размера сайта при прокрутке.

Чтобы было проще, я также создал SASS mixin:

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

Все ответы здесь используют высоту window , на которую влияет строка URL. Все ли забыты о высоте screen ?

Вот мое решение 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); } }); 

Добавление части .css() изменяет неизбежно выровненный по вертикали элемент с выровненным по нижнему краю, поэтому никакого перехода вообще не происходит. Хотя, я полагаю, нет причин просто не добавлять это прямо к нормальному CSS.

Нам нужен сниффер агента пользователя, потому что высота экрана на рабочих столах не помогла бы.

Кроме того, все это предполагает, что #background – элемент фиксированной позиции, заполняющий окно.

Для пуристов JavaScript (предупреждение – непроверено):

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

EDIT: Извините, что это напрямую не отвечает на вашу конкретную проблему более чем одним фоном. Но это один из первых результатов при поиске этой проблемы фиксированных фонов, прыгающих на мобильных устройствах.

Решение, которое я использую сейчас, это проверить userAgent на $(document).ready чтобы узнать, является ли это одним из злоумышленников. Если да, выполните следующие действия:

  1. Установите соответствующие высоты на текущую высоту видового экрана, а не на 100%
  2. Сохранять текущее горизонтальное значение окна просмотра
  3. Затем, в $(window).resize , обновите только соответствующие значения высоты, если новое измерение горизонтального видового экрана отличается от его начального значения
  4. Сохраняйте новые горизонтальные и вертикальные значения

При желании вы также можете проверить разрешающие вертикальные размеры только тогда, когда они превышают высоту адресной строки.

О, и адресная строка влияет на $(window).height . См.: Адресная строка браузера Mobile Webkit (хром) изменяет значение $ (window) .height (); Создание фонового размера: масштабирование обложки каждый раз, когда JS «Окно» ширина-высота против «экрана» ширина-высота?

Я столкнулся с этой проблемой, когда пытался создать экран входа, который будет охватывать весь видовой экран. К сожалению, принятый ответ больше не работает.

1) Элементы с высотой, установленной на 100hv каждый раз при изменении размера видового экрана, включая те случаи, когда это вызвано (dis) появлением строки URL.

2) $(window).height() возвращает значения, также $(window).height() от размера строки URL.

Одним из решений является «замораживание» элемента с использованием transition: height 999999s как было предложено в ответе AlexKempton . Недостатком является то, что это эффективно отключает адаптацию ко всем изменениям размеров видовых экранов, в том числе вызванных вращением экрана.

Поэтому мое решение – управлять изменениями в видовом режиме вручную с помощью JavaScript. Это позволяет мне игнорировать небольшие изменения, которые могут быть вызваны баром URL и реагировать только на большие.

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

EDIT: Я использую эту технику вместе с height: 100hv . Страница отображается правильно с самого начала, а затем JavaScript запускается и начинает управлять высотой вручную. Таким образом, во время загрузки страницы (или даже позже) нет мерцания.

Я нашел очень простое решение без использования Javascript:

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

Все это задерживает движение, так что это невероятно медленно, что это не заметно.

В моем решении было несколько javascript. Держите 100% или 100vh на div (это позволит избежать того, что div не появляется при загрузке начальной страницы). Затем, когда страница загружается, возьмите высоту окна и примените ее к рассматриваемому элементу. Избегает перехода, потому что теперь у вас есть статическая высота на вашем div.

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

Я создал ванильное javascript решение для использования единиц VH. Использование VH практически в любом месте осуществляется путем сокращения адресов на строках. Чтобы зафиксировать jank, который отображается при перерисовке страницы, у меня есть этот js, который будет захватывать все ваши элементы с помощью модулей VH (если вы даете им класс .vh-fix ) и дать им встроенные высоты пикселей. По существу, они замораживаются на высоте, которую мы хотим. Вы можете сделать это при вращении или изменении размера видового экрана, чтобы оставаться отзывчивым.

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

Это решило все мои варианты использования, надеюсь, что это поможет.

Это мое решение для решения этой проблемы, я добавил комментарии непосредственно к коду. Я тестировал это решение и отлично работал. Надеюсь, что мы будем полезны для всех, у нас одна и та же проблема.

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

Это лучшее решение (простейшее) выше всего, что я пробовал.

… И это не сохраняет родной опыт адресной строки !

Вы можете установить высоту с CSS до 100%, например, а затем установить высоту в 0.9 * высоты окна в px с javascript, когда документ будет загружен.

Например, с помощью jQuery:

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

)

К сожалению, нет ничего, что бы работало с чистым CSS: P, но также было бы minfull, что vh и vw работают на iPhone – используйте проценты.

Я установил свой элемент width с помощью javascript. После того, как я установил 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"); 

Это работает для меня. Я не использую jQuery ect. Потому что я хочу, чтобы он загрузился как можно скорее.

Потребовалось несколько часов, чтобы понять все детали этой проблемы и выяснить оптимальную реализацию. Оказывается, с апреля 2016 года только у iOS Chrome есть эта проблема. Я пробовал на Android Chrome и iOS Safari – оба были в порядке без этого исправления. Поэтому исправление для iOS Chrome, которое я использую, это:

 $(document).ready(function() { var screenHeight = $(window).height(); $('div-with-background-image').css('height', screenHeight + 'px'); }); 

Я использую это обходное решение: Исправьте высоту bg1 при загрузке страницы:

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

Затем присоедините прослушиватель событий изменения размера к окну, который делает это: если разница в высоте после изменения размера меньше 60 пикселей (что-то большее, чем высота столбца), ничего не делайте и если оно больше 60 пикселей, то установите высоту bg1 снова на его родительскую высоту! Полный код:

 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: Эта ошибка настолько раздражает!

Подобно @AlexKempton ответ. (Не могу прокомментировать)

Я использовал длительные задержки перехода, чтобы предотвратить изменение размера элемента.

например:

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

Компромисс с этим заключается в том, что он предотвращает изменение размера элемента, включая поворот устройства, однако вы можете использовать некоторые JS для обнаружения изменения orientationchange и сброса высоты, если это было проблемой.