CSS Media Query - Soft-клавиатура нарушает правила ориентации CSS - альтернативное решение? - PullRequest
72 голосов
/ 16 января 2012

Я работаю с несколькими планшетами - как с Android , так и с iOS .В настоящее время у меня есть следующие варианты разрешения для всех планшетов.

  • 1280 x 800
  • 1280 x 768
  • 1024 x 768 (iPad Очевидно) - iPad не имеет этой проблемы

Простейший способ применить стиль на основе ориентации устройства - это использовать ориентацию медиазапроса с использованием следующего синтаксиса.

@media all and (orientation:portrait)
{
  /* My portrait based CSS here */
}

@media all and (orientation:landscape)
{
  /* My landscape based CSS here */
}

Это прекрасно работает на всехпланшетные устройства. НО , проблема в том, что когда устройство находится в портретном режиме и пользователь нажимает на любое поле ввода (например, поиск), выскакивает программная клавиатура - что уменьшает видимую область веб-страницы и заставляет ее отображатьв ландшафтной основе css.На устройствах с планшетом на Android это зависит от высоты клавиатуры.Итак, в конечном итоге веб-страница выглядит испорченной.Поэтому я не могу использовать медиа-запрос ориентации CSS3 для применения стилей на основе ориентации (если нет лучшего медиа-запроса для целевой ориентации).Вот скрипка http://jsfiddle.net/hossain/S5nYP/5/, которая имитирует это - для тестирования устройства используйте полную тестовую страницу - http://jsfiddle.net/S5nYP/embedded/result/

Вот скриншот поведения, взятого с демонстрационной страницы.enter image description here

Итак, есть ли альтернатива для решения этой проблемы, я открыт для решения на основе JavaScript, если не работает нативное решение на основе CSS.

Я нашел фрагмент на http://davidbcalhoun.com/2010/dealing-with-device-orientation, который предлагает добавить класс и цель на основе этого.Например:

<html class="landscape">
  <body>
    <h1 class="landscape-only">Element Heading - Landscape</h1>
    <h1 class="portrait-only">Element Heading - Portrait</h1>
    <!-- .... more... ->

# CSS
.landscape .landscape-only { display:block; }
.landspace .portrait-only  { display:none; }
.portrait .portrait-only   { display:block; }
.portrait .landscape-only  { display:none; }

Что вы, ребята, думаете по этому поводу?У вас есть лучшее решение?

Ответы [ 10 ]

91 голосов
/ 14 ноября 2014

Я знаю, что это на пару лет позже, но я нашел отличное решение

Для пейзажных носителей:

@media screen and (min-aspect-ratio: 13/9) { /* landscape styles here */}

И для портретных носителей:

@media screen and (max-aspect-ratio: 13/9) { /* portrait styles here */}

Полное решение и почему оно работает можно найти здесь Майкл Баррет - Проблемы с Android-браузером

Редактировать: срок действия этой ссылки истек, но моментальный снимок можно найти в интернет-архиве: Майкл Баррет - вызов браузера Android

27 голосов
/ 16 января 2012

Проблема заключается в способе расчета ориентации:

http://www.w3.org/TR/css3-mediaqueries/#orientation

Медиа-функция «Ориентация» является «портретной», если значение медиа-функции «Высота» больше или равно значению медиа-функции «Ширина». В противном случае «ориентация» - это «пейзаж».

Поскольку высота / ширина рассчитывается для видимого окна просмотра, программная клавиатура, по-видимому, вызывает изменение ориентации теперь, когда ширина окна просмотра меньше высоты. Одним из решений было бы просто использовать ваши медиа-запросы, основанные на width. Это делает его более гибким для всех устройств независимо от ориентации, не говоря уже о том, что ширина / высота поддерживается шире, чем ориентация.

Если вы хотите учитывать ширину вместо ориентации, я буду использовать iPhone в качестве примера:

@media screen and (max-width: 320px) {
  /* rules applying to portrait */
}

@media screen and (max-width: 480px) {
  /* rules applying to landscape */
}

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

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

12 голосов
/ 06 сентября 2015

Альтернативой может быть использование device-aspect-ratio, которое остается без изменений. Однако в Webkit вращение устройства не запускает обновление правил CSS с использованием этого запроса, даже если тесты JavaScript возвращают значение true для нового соотношения сторон. Это, по-видимому, из-за ошибки , но я не могу найти отчет об ошибке. Использование комбинации orientation и {min,max}-device-aspect-ratio, кажется, работает нормально:

@media screen and (max-device-aspect-ratio: 1/1) and (orientation: portrait)
@media screen and (min-device-aspect-ratio: 1/1) and (orientation: landscape)

Использование orientation запускает обновления, как и ожидалось, а использование device-aspect-ratio ограничивает обновление действительными изменениями ориентации.

6 голосов
/ 03 декабря 2012

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

// Avoiding the keyboard in Android causing the portrait orientation to change to landscape. 
// Not an issue in IOS. Can use window.orientation.
var currentOrientation = function() {
  // Use screen.availHeight as screen height doesn't change when keyboard displays.  
  if(screen.availHeight > screen.availWidth){
    $("html").addClass('portrait').removeClass('landscape'); 
  } else {
    $("html").addClass('landscape').removeClass('portrait'); 
  }
}

// Set orientation on initiliasation
currentOrientation();
// Reset orientation each time window is resized. Keyboard opening, or change in orientation triggers this.
$(window).on("resize", currentOrientation);
2 голосов
/ 20 сентября 2017

Для меня это помогло:

  @media screen and (max-device-aspect-ratio: 1/1), (max-aspect-ratio: 1/1){
        /*Portrait Mode*/
};

В то время как max-aspect-ratio обеспечивает запуск портретного режима простым изменением размера окна (полезно для ПК и других альбомных устройств), max-device-aspect-ratio помогает со смартфонами или другими устройствами с изменяемой ориентацией. И поскольку я не объявляю конкретные настройки для альбомного режима, даже если max-aspect-ratio сообщает системе> 1, портретный режим все равно будет активирован max-device-aspect-ratio, если устройство Android ориентировано таким образом.

Часть 1/1 в основном означает, что если отношение <= 1, оно переходит в портретный режим, в противном случае он переходит в альбомный режим. </p>

1 голос
/ 14 июля 2013

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

Работает, назначая ширину окна и высоту окна просмотра устройства атрибуту данных для последующей проверки.Поскольку телефоны не меняют ширину при подтягивании клавиатуры, только высота, проверяя соотношение И ширину и исходную ширину, может сказать вам, если клавиатура поднята.Я не нашел варианта использования, который еще не удался, но я уверен, что найду.Если вы все найдете, пожалуйста, дайте мне знать.

Я использую некоторые глобальные переменные, такие как InitialRun и MobileOrientation, которые используются для переключения js, я также использую атрибуты данных html5 для хранения информации в DOM дляманипуляция css.

    var InitialRun = true; // After the initial bootstrapping, this is set to false;
    var MobileOrientation = 'desktop';
    function checkOrientation(winW, winH){ // winW and winH are the window's width and hieght, respectively
        if (InitialRun){
            if (winW > winH){
                $('body').attr('data-height',winW);
                $('body').attr('data-width',winH);
                MobileOrientation = 'landscape';    
                $('body').attr('data-orientation','landscape'); 
            }
            else{
                $('body').attr('data-height',winH);
                $('body').attr('data-width',winW);
                MobileOrientation = 'portrait';
                $('body').attr('data-orientation','portrait');
            }
        }
        else{
            if (winW > winH && winW != $('body').data('width')){
                MobileOrientation = 'landscape';    
                $('body').hdata('orientation','landscape'); //TODO:uncomment
                $('body, #wrapper').css({'height':"100%",'overflow-y':'hidden'});
                //$('body').attr('data-orientation','portrait');
            }
            else{
                MobileOrientation = 'portrait';
                $('body').attr('data-orientation','portrait');
                $('body, #wrapper').css({'height':$('body').data('height'),'overflow-y':'auto'});
            }
        }

    }
0 голосов
/ 26 февраля 2018

Я столкнулся с точно такой же проблемой в iPad.
т.е.когда программная клавиатура появляется в портретном режиме, устройство определяется в горизонтальной ориентации, а стили экрана для альбомной ориентации применяются к экрану, что приводит к неправильному просмотру.

Спецификация устройства

  • Устройство : iPad Mini 4
  • ОС : iOS 11.2.6
  • Разрешение экрана :1024 x 768

к сожалению, для меня это решение не сработало.

@media screen and (min-aspect-ratio: 13/9) { /* landscape styles here */}
@media screen and (max-aspect-ratio: 13/9) { /* portrait styles here */}

Итак, я написал медиа-запрос, подобный этому длямой портретный режим.

@media only screen and (min-width : 300px) and (max-width : 768px) and (orientation : landscape) {
/* portrait styles, when softkeyboard appears, goes here */
}

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

0 голосов
/ 05 мая 2016

Это надежно работает для меня.Я использую http://detectmobilebrowsers.com/ для расширения jQuery для обнаружения $ .browser.mobile.

if ($.browser.mobile) {
  var newOrientationPortrait = true;

//Set orientation based on height/width by default
  if ($(window).width() < $(window).height())
      newOrientationPortrait = true;
  else
      newOrientationPortrait = false;

//Overwrite orientation if mobile browser supports window.orientation
if (window.orientation != null)
    if (window.orientation === 0)
        newOrientationPortrait = true;
    else
        newOrientationPortrait = false;

Вот мой код для изменения области просмотра на основе ориентации.Эта функция предназначена только для мобильных устройств, даже не для планшетов.Это позволяет мне легко писать CSS для 400px и 800px (Portrait vs Landscape).

_onOrientationChange = function() {
    if (_orientationPortrait) 
        $("meta[name=viewport]").attr("content", "width=400,user-scalable=no");
    else 
        $("meta[name=viewport]").attr("content", "width=800");
}

Из-за характера моих требований я не смог сделать это только в CSS Media запросов, так как сам DOMнеобходимо изменить в зависимости от ориентации.К сожалению, на моей работе деловые люди пишут требования к программному обеспечению без предварительной консультации по разработке.

0 голосов
/ 11 июня 2014

Идея: уберите параметр портрета из медиазапроса и оставьте его только с минимальной шириной. Сделайте ваш обычный стиль для портретного режима в этом медиа-запрос. Затем создайте еще один медиа-запрос для ландшафтного режима с минимальной высотой, чтобы браузер не использовал этот запрос при всплывающей клавиатуре. Вы должны поэкспериментировать с тем, что такое «достаточно высокая минимальная высота», но это не должно быть слишком сложно, так как большинство (если не все) ландшафтные режимы имеют высоту, большую, чем при появлении клавиатуры. Кроме того, вы можете добавить минимальную ширину в запрос с альбомной ориентацией, которая больше, чем у большинства смартфонов в портретной ориентации (т.е. около 400 пикселей), чтобы ограничить область запроса.

Вот альтернативное (и ненадежное) решение: - Добавьте пустой произвольный элемент в ваш html, который будет иметь «display: none» во всем, кроме портретного режима. - Создать JQuery или JavaScript слушателя для ввода: фокус. При нажатии на вход ваш javascript проверяет свойство отображения произвольного элемента. Если он возвращает «блок» или что-то еще, что вы установили в портретном режиме, тогда вы можете переопределить свой стиль с помощью JS для запросов в портретном режиме. И наоборот, у вас будет вход: слушатель размытия, чтобы убрать свойства style.cssText элементов, которые вы жестко запрограммировали.

Я сам сейчас экспериментирую с этим - выложу код того, что работает, когда получу что-то солидное и управляемое. (Мое первое решение кажется наиболее разумным).

0 голосов
/ 20 января 2012

Взгляните на эту ссылку: http://www.alistapart.com/articles/a-pixel-identity-crisis/
Может помочь не только ориентация, но и max-device-height или device-pixel-ratio.Во всяком случае, я не проверял это, так что не уверен, что это поможет.

...