CSS Media Query - М'яка клавіатура порушує правила орієнтації CSS - альтернативне рішення?


83

Я працюю з кількома планшетними пристроями - обидва 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/

Ось скріншот поведінки, зроблений із демонстраційної сторінки. введіть тут опис зображення

Отже, чи існує якась альтернатива вирішенню цієї проблеми, я відкритий для рішення на основі 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; }

Що ви думаєте з цього приводу? У вас є краще рішення?


Тільки що дізнався, IPad це НЕ має цієї проблеми. Цю проблему має ТІЛЬКИ ОС Android (стільникові таблетки) та мобільні телефони.
Hossain Khan

Я зіткнувся з подібною проблемою на своєму мобільному веб-сайті. Після тестування на декількох пристроях Android, схоже, це не обмежується жодною конкретною ОС або мобільним / планшетним пристроєм. Схоже, це в першу чергу проблема з пристроями Motorola та Samsung. Мені не вдалося відтворити проблему на нашому телефоні HTC.
TJ Kirchner,

1
Ця проблема в основному стосується андроїд-пристроїв, мобільних пристроїв / планшетів - єдиний спосіб відтворити це - встановити спеціальну клавіатуру, яка має велику висоту, щоб, коли клавіатура відображається, доступна висота для веб-перегляду була меншою за доступну ширину. Тільки тоді веб-переглядач викликає зміну орієнтації. Наприклад, на скріншоті, якщо я можу вимкнути шар пропозицій у верхній частині клавіатури, тоді цієї проблеми не буде, оскільки висота веб-перегляду буде більшою за ширину. Але, як би там не було, я ще не отримав жодного елегантного та ефективного рішення.
Hossain Khan

1
Просто зрозумійте, що ця поведінка в повноекранному веб-додатку IOS 7.0.0 теж має таку поведінку
Олександр

Це сумно. Я не зміг ефективно вирішити проблему, тому позначив це як known limitation.
Hossain Khan

Відповіді:


104

Я знаю, що це запізнилося на пару років, але я знайшов чудове рішення

Для пейзажних засобів масової інформації:

@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
Це вирішує проблему, але створює для мене більше проблем на інших пристроях (переважно на ноутбуках та комп’ютерах)
Стефан Біжзіттер,

На жаль, це рішення працює не на всіх мобільних пристроях.
Діого Кардосо

@StephanBijzitter, можливо, ти міг би використовувати властивість 'max-width'?
Шон Рутледж

3
Це рішення є дуже грубим і не працює на деяких пристроях. Наприклад, мій телефон дає близько 17,7 / 9 при відкритті м'якої клавіатури, тоді як співвідношення сторін альбомної форми набагато менше на багатьох інших пристроях.
raacer

2
Повне посилання на рішення розірвано.
Sparkmorry

27

Проблема полягає у способі обчислення орієнтації:

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

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

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


1
Я розумію, як браузери обчислюють пейзаж та портрет. Але потрібен альтернативний та кращий спосіб вирішити це. Ще одна цікава річ: iPad не викликає зміни орієнтації, коли клавіатура піднята. Я не знаю, чому **** android довелося реалізовувати саме так.
Hossain Khan

Мені просто цікаво, чому вам конкретно потрібна орієнтація пристрою на відміну від просто ширини. Яку проблему ви намагаєтеся вирішити, але лише ширина не вирішить?
scurker

Я працюю з декількома пристроями з різною роздільною здатністю. Не могли б ви навести приклад, як ширину можна використовувати як альтернативу орієнтації? Про використання орієнтації змінюється кілька варіантів зміни орієнтації - зазвичай доступний простір, різний за різною орієнтацією. Отже, деякі елементи можна приховати або змінити розмір залежно від орієнтації. Дякую за допомогу.
Hossain Khan

@HossainKhan @media all and (max-device-wdith:NNNpx){}або @media all and (min-device-wdith:NNNpx){}або@media all and (device-wdith:NNNpx){}
RaphaelDDL

1
врешті-решт, видаливши and (orientation:portrait)та просто застосувавши максимальну та мінімальну ширину, вирішено мою проблему. !!!
Лібін

16

Альтернативою може бути використання 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обмежень, оновлених до фактичних змін орієнтації.


На жаль, ця функція зараз застаріла developer.mozilla.org/en-US/docs/Web/CSS/@media/…
Євген Глухоторенко

середина 2020 року, і це все ще працює, незважаючи на те, що застаріло ... чудове рішення, єдине, що насправді спрацювало у всіх випадках, які я маю!
qraqatit

6

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

Тож я тестував це трохи більше, і це не так прямо. Пристрої Android повинні використовувати screen.availHeight і screen.availWidth. IOS не працює з цим, хоча використовуйте window.orientation для IOS. Робочий стіл повинен використовувати window.innerHeight, window.innerWidth, як ви хочете розміри вікна, а не розміри екрана.
Роббі Дженнінгс,

Я бився головою об стіну за допомогою коду вище. Занадто вибагливий. Я не підтримую робочий стіл для цієї програми, тому я використовую window.orientation - чарівне рішення для Android та IOS. Зараз працює нормально. орієнтація var = Math.abs (window.orientation) === 90? 'пейзаж': 'портрет';
Роббі Дженнінгс,

3

Для мене це зробило фокус:

  @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, воно переходить у портретний режим, інакше переходить в альбомний режим.


2
А як щодо того, коли з’явиться клавіатура?
adi518

Коли віртуальна клавіатура з’являється на мобільному пристрої, нічого не змінюється, оскільки співвідношення сторін пристрою (максимальне співвідношення сторін пристрою) змінюється лише тоді, коли ви фактично обертаєте пристрій або коли навмисно змінюєте орієнтацію екрана з книжкової на альбомну та віце -верса.
helveciofneto

Так, я закінчив впроваджувати та тестувати це для себе. Я розробляю пакет навколо цього: npmjs.com/package/mobile-orientation
adi518

Повернувся , щоб дізнатися більше більше однієї речі: (max-aspect-ratio: 1/1). Здається, нам потрібен цей біт лише для виявлення портрета на робочому столі?
adi518

Правильно. 1/1 - забезпечити, щоб ідеальний квадрат все одно запускав портретний режим (що можливо в системах, що дозволяють змінювати розмір вікна, як вікно браузера на робочому столі). Без цього дивні речі відбуваються саме в такому співвідношенні.
helveciofneto

1

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

    }

1

Я використав простий трюк для вирішення цієї проблеми

@media (max-width: 896px) and (min-aspect-ratio: 13/9){/* Landscape content*/}

Я знайшов максимальну ширину: 896 пікселів можна використовувати для всіх мобільних пристроїв. спробуйте це рішення воно працює!


Ви врятуєте мій день :), але коли повертається з альбомного в портретний, масштаб сторінки порушується, як це зробити?
Амір Фарахані,

Це залежить від поточної максимальної ширини мобільних пристроїв, і при вдосконаленні технології це зміниться. То чи варто нам змінювати сценарій усіх запитів медіа? Я вважаю, що це погана ідея.
QMaster


0

Ідея: Зніміть портретний параметр із медіа-запиту і залиште його лише з мінімальною шириною. Зробіть звичайний стиль для портретного режиму в цьому медіа-запиті. Потім створіть ще один медіа-запит для альбомного режиму з мінімальною висотою, достатньою для того, щоб браузер не використовував цей запит, коли з’явиться клавіатура. Вам доведеться поекспериментувати з тим, що таке ця «досить висока мінімальна висота», але це не повинно бути надто складно, оскільки більшість (якщо не всі) альбомних режимів мають висоту більшу, ніж у вас, коли клавіатура вискакує. Крім того, ви можете додати "мінімальну ширину" до альбомного запиту, яка більша за більшість смартфонів у книжковому вигляді (тобто близько ~ 400 пікселів), щоб обмежити обсяг запиту.

Ось альтернативне (і непомітне) рішення: - Додайте порожній довільний елемент у свій html, який матиме „display: none” у будь-якому іншому режимі, крім портретного. - Створіть прослуховувач jquery або javascript для введення: фокус. Коли натискається вхід, ваш javascript перевіряє властивість відображення довільного елемента. Якщо він повертає "блокувати" або що б ви не встановили під час портретного режиму, ви можете замінити свій стиль за допомогою JS на запити портретного режиму. І навпаки, у вас був би вхідний: blur прослуховувач, щоб згладити властивості style.cssText елементів, які ви жорстко закодували.

Я зараз експериментую з цим - я опублікую код того, що працює, коли отримаю щось надійне та кероване. (Моє перше рішення здається найбільш розумним).


0

Це надійно працює для мене. Я використовую 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

Я зіткнувся з точно такою ж проблемою в 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

Оскільки iPhone 11 Pro Max Viewport становить 414 x 896 PX - цього повинно бути достатньо, щоб мати орієнтацію: альбомний з мінімальною шириною: 500 пікселів

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.