iOS 7 iPad Safari Landscape внутренняя высота / внешняя проблема макета высоты
Мы видим проблемы с веб-приложением, которое имеет высоту 100% в Safari в iOS 7. Похоже, что window.innerHeight (672px) не соответствует window.outerHeight (692px), но только в ландшафтном режиме. В конечном итоге происходит то, что в приложении со 100% ростом на теле вы получаете 20 пикселей дополнительного пространства. Это означает, что когда пользователь нажимает на наше приложение, элементы навигации оказываются за хромом браузера. Это также означает, что любые абсолютно позиционированные элементы, которые находятся внизу экрана, в конечном итоге отключаются на 20 пикселей.
Эта проблема также была изложена в этом вопросе здесь: IOS 7 - CSS - высота HTML - 100% = 692 пикселей
И можно увидеть на этом неоднозначном скриншоте:
То, что мы пытаемся сделать, это взломать, чтобы до тех пор, пока Apple не исправит ошибку, нам не придется беспокоиться об этом.
Один из способов сделать это - абсолютно позиционировать тело только в iOS 7, но это в значительной степени помещает дополнительные 20 пикселей вверху страницы, а не внизу:
body {
position: absolute;
bottom: 0;
height: 672px !important;
}
Будем весьма благодарны за любую помощь в приведении externalHeight в соответствие с innerHeight или хакерской атакой, чтобы наши пользователи не могли видеть эту проблему.
13 ответов
В моем случае решением было изменить позиционирование на фиксированное:
@media (orientation:landscape) {
html.ipad.ios7 > body {
position: fixed;
bottom: 0;
width:100%;
height: 672px !important;
}
}
Я также использовал скрипт для определения iPad с iOS 7:
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i)) {
$('html').addClass('ipad ios7');
}
Простое и понятное решение только для CSS:
html {
height: 100%;
position: fixed;
width: 100%;
}
iOS 7, кажется, правильно устанавливает высоту с этим. Кроме того, нет необходимости изменять размеры событий javascript и т. Д. Поскольку вы работаете с приложением полной высоты, на самом деле не имеет значения, всегда ли оно фиксировано.
Ответ Сэмюэля, как также заявил Терри Торсен, работает отлично, но не получается, если веб-страница была добавлена на домашнюю страницу iOS.
Более интуитивным решением было бы проверить window.navigator.standalone
вар.
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && !window.navigator.standalone) {
$('html').addClass('ipad ios7');
}
Таким образом, он применяется только при открытии внутри Safari, а не при запуске из дома.
Я использовал это решение JavaScript для решения этой проблемы:
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && window.innerHeight != document.documentElement.clientHeight) {
var fixViewportHeight = function() {
document.documentElement.style.height = window.innerHeight + "px";
if (document.body.scrollTop !== 0) {
window.scrollTo(0, 0);
}
}.bind(this);
window.addEventListener("scroll", fixViewportHeight, false);
window.addEventListener("orientationchange", fixViewportHeight, false);
fixViewportHeight();
document.body.style.webkitTransform = "translate3d(0,0,0)";
}
Ответ Сэмюэля самый лучший, хотя он ломается, если пользователь добавляет страницу на свой домашний экран (страницы на домашнем экране не показывают ошибку). Проверьте innerHeight перед добавлением класса следующим образом:
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i)) {
if(window.innerHeight==672){
$('html').addClass('ipad ios7');
}
}
Обратите внимание, что ошибка также не отображается при просмотре в Интернете.
Вариант подхода Самуила, но с положением: -webkit-sticky set на html работал для меня лучше всего.
@media (orientation:landscape) {
html.ipad.ios7 {
position: -webkit-sticky;
top: 0;
width: 100%;
height: 672px !important;
}
}
Обратите внимание: "top: 0", а не "bottom: 0", а целевым элементом является "html", а не "body"
Принятый ответ не справляется, когда отображается панель избранного. Вот улучшенный улов всех исправлений:
@media (orientation:landscape) {
html.ipad.ios7 > body {
position: fixed;
height: calc(100vh - 20px);
width:100%;
}
}
Вам нужно JavaScript, чтобы обойти эту ошибку. window.innerHeight
имеет правильную высоту. Вот самое простое решение, которое я могу придумать:
$(function() {
function fixHeightOnIOS7() {
var fixedHeight = Math.min(
$(window).height(), // This is smaller on Desktop
window.innerHeight || Infinity // This is smaller on iOS7
);
$('body').height(fixedHeight);
}
$(window).on('resize orientationchange', fixHeightOnIOS7);
fixHeightOnIOS7();
});
Вам также нужно будет установить position: fixed
на <body>
,
Вот полный рабочий пример:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<title>iOS7 height bug fix</title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
$(function() {
function fixHeightOnIOS7() {
var fixedHeight = Math.min(
$(window).height(),
window.innerHeight || Infinity
);
$('body').height(fixedHeight);
}
$(window).on('resize orientationchange', fixHeightOnIOS7);
fixHeightOnIOS7();
// Generate content
var contentHTML = $('#content').html();
for (var i = 0; i < 8; i++) contentHTML += contentHTML;
$('#content').html(contentHTML);
});
</script>
<style>
html,
body
{
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: auto;
position: fixed;
}
#page-wrapper
{
height: 100%;
position: relative;
background: #aaa;
}
#header,
#footer
{
position: absolute;
width: 100%;
height: 30px;
background-color: #666;
color: #fff;
}
#footer
{
bottom: 0;
}
#content
{
position: absolute;
width: 100%;
top: 30px;
bottom: 30px;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
</style>
</head>
<body>
<div id="page-wrapper">
<div id="header">Header</div>
<div id="content">
<p>Lorem ipsum dolor sit amet.</p>
</div>
<div id="footer">Footer</div>
</div>
</body>
</html>
Я наткнулся на эту страницу по той же проблеме. Здесь много полезных ответов, а других нет (для меня).
Однако я нашел решение, которое работает в моем случае и работает совершенно независимо от того, какая версия ОС и какая ошибка сейчас, в прошлом или будущем.
Объяснение: Разработка веб-приложения (без встроенного приложения) с несколькими модулями фиксированного размера в полноэкранном режиме с именем класса "модуль".
.module {position:absolute; top:0; right:0; bottom:0; left:0;}
который содержит нижний колонтитул с именем класса "нижний колонтитул"
.module > .footer {position:absolute; right:0; bottom:0; left:0; height:90px;}
Не берите в голову, если я позже установлю высоту нижнего колонтитула на другую высоту, или даже его высота будет установлена его содержимым, я могу использовать следующий код для исправления:
function res_mod(){
$('.module').css('bottom', 0); // <-- need to be reset before calculation
var h = $('.module > .footer').height();
var w = window.innerHeight;
var o = $('.module > .footer').offset();
var d = Math.floor(( w - o.top - h )*( -1 ));
$('.module').css('bottom',d+'px'); // <--- this makes the correction
}
$(window).on('resize orientationchange', res_mod);
$(document).ready(function(){
res_mod();
});
Благодаря навыкам Маттео Спинелли, я все еще могу без проблем использовать iScroll, поскольку, к счастью, после него происходят изменения. В противном случае необходимо будет повторно вызвать iScroll-init после исправления.
Надеюсь, это кому-нибудь поможет
В основном есть две ошибки - высота окна в ландшафтном режиме и положение прокрутки, когда пользователь возвращается к нему из портретного режима. Мы решили это так:
высота окна контролируется:
// window.innerHeight is not supported by IE
var winH = window.innerHeight ? window.innerHeight : $(window).height();
// set the hight of you app
$('#yourAppID').css('height', winH);
// scroll to top
window.scrollTo(0,0);
Теперь вышесказанное можно поместить в функцию и связать с событиями изменения размера окна и / или изменения ориентации. вот и все... см. пример:
Со ссылкой на принятый ответ мне также повезло со следующим правилом:
html.ipad.ios7 {
position: fixed;
width: 100%;
height: 100%;
}
Это имеет дополнительное преимущество в том, что, по-видимому, останавливает прокрутку html-элемента "под" фиксированным элементом body.
Если я использую это:
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && !window.navigator.standalone) {
$('html').addClass('ipad ios7');
}
Мой Safari на Mac показывает те же классы HTML... так что он не работает правильно.
Я попытался объединить несколько вещей - это помогло мне, поэтому я могу управлять им в браузере и без просмотра в браузере.
JQuery
if (navigator.userAgent.match(/iPad/i) && (window.orientation) ){
$('html').addClass('ipad ');
if (window.innerHeight != window.outerHeight ){
$('html').addClass('browser landscape');
}
else{
$('html').addClass('browser portrait');
}
}
CSS
@media (orientation:landscape) {
html.ipad.browser > body {
position: fixed;
height: 671px !important;
}
}
///// С этим вы более гибкие или другие ОС и браузеры
Что если ты попробуешь
html{ bottom: 0;padding:0;margin:0}body {
position: absolute;
bottom: 0;
height: 672px !important;
}