CSS Media Query – Soft-keyboard rompe las reglas de orientación css – ¿solución alternativa?

Estoy trabajando con varios dispositivos de tableta, ambos Android y iOS . Actualmente tengo las siguientes variaciones de resolución para todas las tabletas.

  • 1280 x 800
  • 1280 x 768
  • 1024 x 768 (iPad obviamente) – iPad no tiene este problema

La forma más simple de aplicar el estilo basado en la orientación del dispositivo es usar la orientación de la consulta de medios usando la siguiente syntax.

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

Esto funciona perfectamente bien en todos los dispositivos de tableta. PERO , el problema es que cuando el dispositivo está en modo vertical y el usuario toca en cualquier campo de entrada (por ejemplo, búsqueda) aparece el teclado virtual, lo que reduce el área visible de la página web y la fuerza a renderizar en formato horizontal. En dispositivos con tableta Android, depende de la altura del teclado. Por lo tanto, en última instancia, la página web se ve rota. Por lo tanto, no puedo usar la consulta de medios de orientación de CSS3 para aplicar estilos basados ​​en la orientación (a menos que haya una mejor consulta de medios a la orientación del objective). Aquí hay un violín http://jsfiddle.net/hossain/S5nYP/5/ que emula esto – para pruebas de dispositivos use la página de prueba completa – http://jsfiddle.net/S5nYP/embedded/result/

Aquí hay una captura de pantalla del comportamiento tomado de la página de demostración. enter image description here

Entonces, ¿hay alguna alternativa para abordar este problema, estoy abierto a la solución basada en JavaScript si la solución nativa basada en CSS no funciona?

Encontré un fragmento en http://davidbcalhoun.com/2010/decision-with-device-orientation que sugiere agregar clases y objectives en función de eso. Por ejemplo:

   

Element Heading - Landscape

Element Heading - Portrait

Sé que esto es un par de años tarde, pero encontré una gran solución

Para los medios de paisaje:

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

Y para los medios de retrato:

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

La solución completa y por qué funciona se puede encontrar aquí Michael Barret: desafíos del navegador Android

El problema radica en la forma en que se calcula la orientación:

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

La característica de “orientación” de los medios es ‘retrato’ cuando el valor de la función de medios de ‘altura’ es mayor o igual que el valor de la función de medios de ‘ancho’. De lo contrario, ‘orientación’ es ‘paisaje’.

Dado que el alto / ancho se calcula en la ventana visible, el teclado virtual aparentemente hace que la orientación se invierta ahora que el ancho de la ventana gráfica es menor que la altura. Una solución sería simplemente usar sus consultas de medios basadas solo en el width . Esto lo hace más flexible en todos los dispositivos, independientemente de la orientación, sin mencionar que el ancho / alto es más compatible que la orientación.

Si quieres contabilizar el ancho en lugar de la orientación, usaré el iPhone como ejemplo:

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

Este enfoque es más flexible que la orientación ya que las consultas no están limitadas a dispositivos / agentes de usuario que admiten orientación, sin mencionar que la orientación le dice muy poco en comparación con el ancho.

Por supuesto, si realmente necesita saber la orientación, parece que configurar la clase inicialmente y solo usar esa podría ser su mejor opción.

Una alternativa podría ser usar device-aspect-ratio , que permanece sin cambios. Sin embargo, en Webkit, al rotar el dispositivo no se activa una actualización de las reglas CSS mediante esta consulta, aunque las pruebas de JavaScript devuelven verdadero para la nueva relación de aspecto. Esto aparentemente se debe a un error , pero no puedo encontrar un informe de error. Usar una combinación de orientation y {min,max}-device-aspect-ratio parece funcionar bien:

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

El uso de la orientation activa las actualizaciones como se esperaba, y el uso de las restricciones de device-aspect-ratio del device-aspect-ratio actualizadas a los cambios reales de orientación.

Trabajé a través de las opciones enumeradas anteriormente y ninguna me solucionó los problemas. Cambié al uso de screen.availHeight ya que brinda resultados de altura consistente evitando el problema de visualización del teclado.

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

He revisado varias de las respuestas anteriores y ninguna de ellas hizo exactamente lo que yo quería, es decir, imitar la funcionalidad del iPhone lo más fielmente posible. Lo siguiente es lo que está funcionando para mí en la producción ahora.

Funciona asignando el ancho y el alto de la ventana de la ventana gráfica del dispositivo a un atributo de datos para futuras comprobaciones. Como los teléfonos no cambian el ancho de la página al tirar del teclado, solo la altura, verificando la relación Y el ancho contra el ancho original puede indicar si el teclado está arriba. No he encontrado un caso de uso que haya fallado todavía, pero estoy seguro de que lo haré. Si todos encuentran uno, háganmelo saber.

Estoy usando algunos elementos globales, como InitialRun y ​​MobileOrientation, que se usan para el cambio de js, también estoy usando atributos de datos html5 para almacenar información en el DOM para la manipulación de 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'}); } } } 

Para mí, esto hizo el truco:

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

Mientras que la max-aspect-ratio se encarga de activar el modo vertical simplemente redimensionando la ventana (útil para PC y otros dispositivos de solo paisaje), la max-device-aspect-ratio ayuda con los teléfonos inteligentes u otros dispositivos con orientación variable. Y como no estoy declarando configuraciones específicas para el modo Paisaje, incluso si max-aspect-ratio está informando> 1 en el sistema, el modo Retrato todavía se activará con la relación max-device-aspect-ratio del dispositivo si el dispositivo Android está orientado de esa manera .

La parte 1/1 significa básicamente que si la relación es <= 1, pasa al modo vertical, de lo contrario pasa al modo horizontal.

Eche un vistazo a este enlace: http://www.alistapart.com/articles/a-pixel-identity-crisis/
Confiar no solo en la orientación, sino también en max-device-height o device-pixel-ratio puede ayudar. De todos modos, no lo probé, así que no estoy seguro de que sea útil.

Idea: quite el parámetro de retrato de su consulta multimedia y déjelo solo con un ancho mínimo. Haga su estilo normal para el modo vertical en esa consulta de medios. Luego, cree otra consulta de medios para el modo horizontal con una altura mínima lo suficientemente alta para que el navegador no use esa consulta cuando aparezca el teclado. Tendría que experimentar con lo que es ‘altura suficientemente alta’, pero no debería ser demasiado difícil ya que la mayoría de los modos de paisaje (si no todos) tienen una altura mayor de la que tendría cuando aparece un teclado. Además, puede agregar un ‘min-width’ a la consulta de paisaje que es más grande que la mayoría de los teléfonos inteligentes en la vista vertical (es decir, alrededor de ~ 400px) para limitar el scope de la consulta.

Aquí hay una solución alternativa (y tenue): – Agregue un elemento arbitrario vacío a su html que tendrá ‘display: none’ en cualquier otra cosa que no sea el modo vertical. – Crea un oyente jquery o javascript para la entrada: foco. Cuando se hace clic en una entrada, su javascript verifica la propiedad de visualización del elemento arbitrario. Si devuelve ‘bloque’ o lo que sea que hayas configurado durante el modo vertical, puedes anular tu estilo con JS a tus consultas en modo retrato. Por el contrario, tendría una entrada: desenfoque el oyente para borrar las propiedades style.cssText de los elementos que ha codificado.

Estoy experimentando con esto ahora mismo: publicaré el código de lo que funciona cuando obtengo algo sólido y manejable. (Mi primera solución parece ser la más razonable).

Esto funciona de manera confiable para mí. Estoy usando http://detectmobilebrowsers.com/ para la extensión jQuery para detectar $ .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; 

Aquí está mi código para modificar la ventana gráfica según la orientación. Esta función solo se utiliza para dispositivos móviles, ni siquiera en tabletas. Esto me permite escribir CSS fácilmente para 400px y 800px (Retrato versus Paisaje).

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

Debido a la naturaleza de mis requisitos, no pude hacer esto solo en las consultas de CSS Media, ya que el DOM en sí tenía que cambiar en función de la orientación. Desafortunadamente en mi trabajo, los empresarios escriben los requisitos de software sin consultar el desarrollo primero.

Me enfrenté al mismo problema en el iPad.
es decir; cuando el teclado virtual aparece en modo vertical, el dispositivo se detecta en orientación horizontal y los estilos de paisaje se aplican a la pantalla, lo que da como resultado una vista desordenada.

Especificación del dispositivo

  • Dispositivo : iPad Mini 4
  • OS : iOS 11.2.6
  • Resolución de pantalla : 1024 x 768

desafortunadamente, para mí, esta solución no funcionó.

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

Entonces, lo que hice fue escribir una consulta de medios como esta para mi modo de retrato.

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

es decir; cuando aparece el teclado virtual, la altura de la pantalla se reduce pero el ancho de la pantalla permanece en 768 px, lo que dio como resultado una pantalla de detección de consultas multimedia como orientación horizontal. De ahí el trabajo alrededor dado como arriba.