CSS Media Query - Soft-клавиатура нарушает правила ориентации CSS - альтернативное решение?

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

  • 1280 x 800
  • 1280 x 768
  • 1024 x 768 (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; }

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

Ответ 1

Я знаю, что это несколько лет назад, но я нашел отличное решение

Для пейзажных СМИ:

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

И для портретных СМИ:

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

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

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

Ответ 2

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

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 */
}

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

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

Ответ 3

Альтернативой может быть использование device-aspect-ratio, который остается неизменным. Тем не менее, в Webkit вращение устройства не вызывает обновление правил CSS с использованием этого запроса, даже если тесты JavaScript вернутся к новому соотношению сторон. Это, по-видимому, из-за ошибки, но я не могу найти отчет об ошибке. Использование комбинации 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 ограничивает обновление до фактических изменений ориентации.

Ответ 4

Я работал над перечисленными выше опциями, и никто не исправил проблемы для меня. Я переключился на использование 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);

Ответ 5

Для меня это сделало трюк:

  @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 системе, режим Portrait будет по-прежнему запускаться с помощью max-device-aspect-ratio, если Android-устройство ориентировано именно так.

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

Ответ 6

Я рассмотрел несколько вышеперечисленных ответов, и ни один из них не сделал то, что я хотел, чтобы максимально точно имитировать функциональность 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 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'});
            }
        }

    }

Ответ 7

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

Ответ 8

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

Здесь альтернативное (и слабое) решение: - Добавить пустой произвольный элемент в ваш html, который будет иметь "display: none" в чем-либо, кроме портретного режима. - Создайте прослушиватель jquery или javascript для ввода: focus. Когда щелкнул вход, ваш javascript проверяет свойство отображения произвольного элемента. Если он вернет "блок" или что-то еще, что вы его установили в портретном режиме, вы можете переопределить свой стиль с помощью JS для запросов в портретном режиме. И наоборот, у вас будет вход: blur listener, чтобы очистить свойства style.cssText элементов, которые вы жестко закодировали.

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

Ответ 9

Это работает надежно для меня. Я использую 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 должен был меняться в зависимости от ориентации. К сожалению, на моей работе, деловые люди пишут требования к программному обеспечению, не консультируясь с разработкой в ​​первую очередь.

Ответ 10

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

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

  • Устройство: iPad Mini 4
  • ОС: iOS 11.2.6
  • Разрешение экрана: 1024 х 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 пикселей, в результате чего медиазапрос обнаруживает экран в горизонтальной ориентации. Отсюда и обходной путь, указанный выше.