CSS Media Query - Softtastatur bricht CSS-Orientierungsregeln - alternative Lösung?

82

Ich arbeite mit mehreren Tablet-Geräten - beide Android und iOS. Derzeit habe ich folgende Auflösungsvarianten für alle Tablets.

  • 1280 x 800
  • 1280 x 768
  • 1024 x 768 (iPad offensichtlich) - iPad hat dieses Problem nicht

Die einfachste Möglichkeit, einen auf Geräteorientierung basierenden Stil anzuwenden, besteht darin, die Ausrichtung der Medienabfrage mithilfe der folgenden Syntax zu verwenden.

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

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

Dies funktioniert auf allen Tablet-Geräten einwandfrei. ABER das Problem ist, wenn sich das Gerät im Hochformat befindet und der Benutzer auf ein Eingabefeld tippt (z. B. Suchen), wird die Softtastatur angezeigt. Dadurch wird der sichtbare Bereich der Webseite verkleinert und zum Rendern in CSS im Querformat gezwungen. Bei Android-Tablet-Geräten hängt dies von der Höhe der Tastatur ab. Letztendlich sieht die Webseite also kaputt aus. Daher kann ich die Orientierungsmedienabfrage von CSS3 nicht verwenden, um Stile basierend auf der Orientierung anzuwenden (es sei denn, es gibt eine bessere Medienabfrage für die Zielorientierung). Hier ist eine Geige http://jsfiddle.net/hossain/S5nYP/5/, die dies emuliert - für Gerätetests verwenden Sie die vollständige Testseite - http://jsfiddle.net/S5nYP/embedded/result/

Hier ist ein Screenshot des Verhaltens auf der Demoseite. Geben Sie hier die Bildbeschreibung ein

Gibt es eine Alternative, um dieses Problem zu lösen? Ich bin offen für JavaScript-basierte Lösungen, wenn native CSS-basierte Lösungen nicht funktionieren.

Ich habe auf http://davidbcalhoun.com/2010/dealing-with-device-orientation einen Ausschnitt gefunden, der vorschlägt, darauf basierend Klasse und Ziel hinzuzufügen. Beispielsweise:

<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; }

Was haltet ihr davon? Hast du eine bessere Lösung?

Hossain Khan
quelle
Gerade herausgefunden, iPad hat nicht dieses Problem haben. NUR Android OS (Wabentabletten) und Handys hat dieses Problem.
Hossain Khan
Ich bin auf ein ähnliches Problem mit meiner mobilen Website gestoßen. Nach dem Testen auf mehreren Android-Geräten scheint es nicht auf ein bestimmtes Betriebssystem oder Mobil- / Tablet-Gerät beschränkt zu sein. Es sieht so aus, als wäre es hauptsächlich ein Problem mit Motorola- und Samsung-Geräten. Ich konnte das Problem auf unserem HTC-Telefon nicht reproduzieren.
TJ Kirchner
1
Dieses Problem tritt hauptsächlich bei Android-Geräten, Mobilgeräten / Tablets auf. Sie können dies nur reproduzieren, indem Sie eine benutzerdefinierte Tastatur mit großer Höhe installieren. Wenn die Tastatur angezeigt wird, ist die verfügbare Höhe für die Webansicht geringer als die verfügbare Breite. Nur dann löst Webview eine Orientierungsänderung aus. Wenn ich im Screenshot beispielsweise die Vorschlagsebene oben auf der Tastatur deaktivieren kann, ist dieses Problem nicht vorhanden, da die Höhe der Webansicht größer als die Breite ist. Trotzdem habe ich noch keine elegante und effiziente Lösung.
Hossain Khan
1
Stellen Sie einfach fest, dass IOS 7.0.0 WebApp im Vollbildmodus auch dieses Verhalten aufweist
Alexandre
Das ist traurig. Ich konnte das Problem nicht effizient lösen und habe es daher als markiert known limitation.
Hossain Khan

Antworten:

105

Ich weiß, dass dies ein paar Jahre zu spät ist, aber ich habe eine großartige Lösung gefunden

Für Landschaftsmedien:

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

Und für Porträtmedien:

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

Die vollständige Lösung und warum es funktioniert, finden Sie hier. Michael Barret - Herausforderungen für Android-Browser

Bearbeiten: Dieser Link ist jetzt abgelaufen, aber ein Schnappschuss kann im Internetarchiv gefunden werden: Michael Barret - Herausforderungen für Android-Browser

Sean Routledge
quelle
1
Es löst das Problem, schafft aber mehr Probleme auf anderen Geräten für mich (hauptsächlich Laptops und Computer)
Stephan Bijzitter
Leider funktioniert diese Lösung nicht auf allen Mobilgeräten.
Diogo Cardoso
@StephanBijzitter Vielleicht könnten Sie die Eigenschaft 'max-width' verwenden?
Sean Routledge
3
Diese Lösung ist sehr rau und funktioniert auf einigen Geräten nicht. Zum Beispiel gibt mein Telefon beim Öffnen der Softtastatur etwa 17,7 / 9 aus, während das Seitenverhältnis im Querformat bei vielen anderen Geräten viel geringer ist.
Raacer
2
Der vollständige Lösungslink ist unterbrochen.
Sparkmorry
27

Das Problem liegt in der Art und Weise, wie die Orientierung berechnet wird:

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

Die Medienfunktion "Ausrichtung" ist "Hochformat", wenn der Wert der Medienfunktion "Höhe" größer oder gleich dem Wert der Medienfunktion "Breite" ist. Ansonsten ist "Orientierung" "Landschaft".

Da die Höhe / Breite im sichtbaren Ansichtsfenster berechnet wird, bewirkt die Softtastatur anscheinend, dass die Ausrichtung jetzt umgedreht wird, da die Breite des Ansichtsfensters kleiner als die Höhe ist. Eine Lösung wäre, stattdessen nur Ihre Medienabfragen zu widthverwenden. Dies macht es geräteübergreifend flexibler, unabhängig von der Ausrichtung, ganz zu schweigen davon, dass Breite / Höhe stärker unterstützt wird als die Ausrichtung.

Wenn Sie die Breite anstelle der Ausrichtung berücksichtigen möchten, verwende ich das iPhone als Beispiel:

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

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

Dieser Ansatz ist flexibler als die Ausrichtung, da die Abfragen nicht auf Geräte / Benutzeragenten beschränkt sind, die die Ausrichtung unterstützen, ganz zu schweigen davon, dass die Ausrichtung nur sehr wenig über die Breite aussagt.

Wenn Sie die Orientierung wirklich kennen müssen, scheint es natürlich so, als würden Sie die Klasse zunächst festlegen und nur diese Option verwenden.

Scurker
quelle
1
Ich verstehe, wie Querformat und Hochformat von den Browsern berechnet werden. Aber brauchen alternative und bessere Möglichkeit, dies zu handhaben. Eine weitere interessante Sache ist, dass das iPad keine Orientierungsänderung auslöst, wenn die Tastatur geöffnet ist. Ich weiß nicht, warum der **** Android so umsetzen musste.
Hossain Khan
Ich bin nur neugierig, warum Sie speziell die Ausrichtung des Geräts und nicht nur die Breite benötigen. Was ist das Problem, das Sie lösen möchten und das nur durch die Breite allein nicht behoben werden kann?
Scurker
Ich arbeite mit mehreren Geräten mit unterschiedlicher Auflösung. Könnten Sie bitte ein Beispiel geben, wie die Breite als Alternative zur Orientierung verwendet werden kann? Über die Verwendung von Orientierungsänderungen gibt es mehrere Anwendungen für Orientierungsänderungen - normalerweise verfügbarer Platz, der sich in verschiedenen Orientierungen unterscheidet. Daher können einige Elemente je nach Ausrichtung ausgeblendet oder in der Größe geändert werden. Danke für all die Hilfe.
Hossain Khan
@HossainKhan @media all and (max-device-wdith:NNNpx){}oder @media all and (min-device-wdith:NNNpx){}oder@media all and (device-wdith:NNNpx){}
RaphaelDDL
1
and (orientation:portrait)Letztendlich wurde mein Problem durch Entfernen und Anwenden der maximalen und minimalen Breite behoben. !!!
Libin
16

Eine Alternative könnte die Verwendung sein device-aspect-ratio, die unverändert bleibt. In Webkit löst das Drehen des Geräts jedoch keine Aktualisierung der CSS-Regeln mithilfe dieser Abfrage aus, obwohl JavaScript-Tests für das neue Seitenverhältnis true zurückgeben. Dies ist anscheinend auf einen Fehler zurückzuführen , aber ich kann keinen Fehlerbericht finden. Die Verwendung einer Kombination aus orientationund {min,max}-device-aspect-ratioscheint gut zu funktionieren:

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

Die Verwendung von orientationlöst Auslösungen wie erwartet aus, und die Verwendung von device-aspect-ratioEinschränkungen wird auf tatsächliche Orientierungsänderungen aktualisiert.

muru
quelle
Leider ist diese Funktion jetzt veraltet. Developer.mozilla.org/en-US/docs/Web/CSS/@media/…
Eugene Gluhotorenko
Mitte 2020 und das funktioniert immer noch, obwohl es veraltet ist ... großartige Lösung, die einzige, die in allen Fällen, die ich habe, tatsächlich für mich funktioniert hat!
Qraqatit
6

Ich habe die oben aufgeführten Optionen durchgearbeitet und keine hat die Probleme für mich ganz behoben. Ich habe auf screen.availHeight umgestellt, da es konsistente Höhenergebnisse liefert, um das Problem mit der Tastaturanzeige zu vermeiden.

// 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);
Robby Jennings
quelle
Also habe ich das ein bisschen mehr getestet und es ist nicht so einfach. Android-Geräte müssen screen.availHeight und screen.availWidth verwenden. IOS ist mit diesen fehlerhaft, verwenden Sie also window.orientation für IOS. Der Desktop sollte window.innerHeight, window.innerWidth verwenden, da die Fensterabmessungen nicht die Bildschirmabmessungen sein sollen.
Robby Jennings
Ich habe meinen Kopf mit dem obigen Code gegen die Wand geschlagen. Zu pingelig. Ich unterstütze Desktop für diese App nicht, daher verwende ich window.orientation ist die magische Lösung für Android und IOS. Funktioniert jetzt gut. var Orientierung = Math.abs (Fensterorientierung) === 90? 'Landschaftsportrait';
Robby Jennings
3

Für mich war das der Trick:

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

Während max-aspect-ratiodas Auslösen des Portrait-Modus durch einfaches Ändern der Fenstergröße (nützlich für PCs und andere Nur-Querformat-Geräte) max-device-aspect-ratioerledigt wird , hilft dies bei Smartphones oder anderen Geräten mit variabler Ausrichtung. Und da ich keine spezifischen Einstellungen für den Querformatmodus deklariere max-aspect-ratio, wird der Hochformatmodus auch dann ausgelöst, max-device-aspect-ratiowenn das Android-Gerät so ausgerichtet ist , auch wenn dem System> 1 gemeldet wird .

Der 1/1Teil bedeutet im Grunde, dass wenn das Verhältnis <= 1 ist, es in den Hochformatmodus wechselt, andernfalls geht es in den Querformatmodus.

helveciofneto
quelle
2
Was ist, wenn die Tastatur hochgefahren wird?
adi518
Wenn die virtuelle Tastatur auf einem mobilen Gerät angezeigt wird, ändert sich nichts, da sich das Seitenverhältnis des Geräts (maximales Seitenverhältnis des Geräts) nur ändert, wenn Sie das Gerät tatsächlich drehen oder wenn Sie die Bildschirmausrichtung absichtlich von Hochformat auf Querformat und Schraubstock ändern -versa.
helveciofneto
Ja, ich habe es schließlich selbst implementiert und getestet. Ich entwickle ein Paket dazu: npmjs.com/package/mobile-orientation
adi518
Kam zurück, um sich über eine weitere Sache zu erkundigen : (max-aspect-ratio: 1/1). Es scheint, wir brauchen dieses Bit nur, um ein Porträt auf dem Desktop zu erkennen?
adi518
Richtig. Mit 1/1 soll sichergestellt werden, dass ein perfektes Quadrat weiterhin den Porträtmodus auslöst (was in Systemen möglich ist, die eine Größenänderung des Fensters ermöglichen, wie z. B. einem Browserfenster auf einem Desktop). Ohne sie passieren seltsame Dinge in genau diesem Verhältnis.
Helveciofneto
2

Ich habe einen einfachen Trick benutzt, um dieses Problem zu lösen

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

Ich fand maximale Breite: 896px kann für alle mobilen Geräte verwendet werden. Probieren Sie diese Lösung aus, es funktioniert!

Mohit Soni
quelle
Sie retten meinen Tag :), aber wenn es von Querformat zu Hochformat zurückkommt, ist der Zoom der Seite kaputt, wie damit umzugehen?
Amir Farahani
1

Ich habe einige der obigen Antworten durchgesehen und keine von ihnen hat genau das getan, was ich wollte, nämlich die iPhone-Funktionalität so genau wie möglich nachzuahmen. Folgendes funktioniert jetzt für mich in der Produktion.

Dabei wird die Fensterbreite und -höhe des Geräteansichtsfensters einem Datenattribut zur zukünftigen Überprüfung zugewiesen. Da Telefone beim Hochziehen der Tastatur die Größe nicht ändern, können Sie nur anhand der Höhe, wenn Sie das Verhältnis UND die Breite mit der ursprünglichen Breite vergleichen, feststellen, ob die Tastatur aktiv ist. Ich habe noch keinen Anwendungsfall gefunden, der fehlgeschlagen ist, aber ich bin mir sicher, dass ich es tun werde. Wenn Sie alle einen finden, lassen Sie es mich bitte wissen.

Ich verwende einige globale Elemente wie InitialRun und MobileOrientation, die für das js-Switching verwendet werden. Außerdem verwende ich HTML5-Datenattribute, um Informationen im DOM für die CSS-Manipulation zu speichern.

    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'});
            }
        }

    }
dortbelrobot
quelle
0

Schauen Sie sich diesen Link an: http://www.alistapart.com/articles/a-pixel-identity-crisis/
Verlassen Sie sich nicht nur auf die Orientierung, sondern auch auf max-device-heightoder device-pixel-ratiokann helfen. Wie auch immer, ich habe es nicht getestet, also nicht sicher, ob es helfen wird.

Sergiy T.
quelle
0

Idee: Nehmen Sie den Porträtparameter aus Ihrer Medienabfrage und lassen Sie ihn nur mit einer minimalen Breite. Führen Sie in dieser Medienabfrage Ihr normales Styling für den Hochformatmodus durch. Erstellen Sie dann eine weitere Medienabfrage für den Querformatmodus mit einer Mindesthöhe, die groß genug ist, damit der Browser diese Abfrage nicht verwendet, wenn die Tastatur angezeigt wird. Sie müssten experimentieren, was diese "Mindesthöhe" ist, aber es sollte nicht zu schwierig sein, da die meisten (wenn nicht alle) Landschaftsmodi eine größere Höhe haben als beim Aufspringen einer Tastatur. Darüber hinaus können Sie der Querformatabfrage eine Mindestbreite hinzufügen, die größer ist als die der meisten Smartphones in der Hochformatansicht (dh ca. 400 Pixel), um den Umfang der Abfrage einzuschränken.

Hier ist eine alternative (und schwache) Lösung: - Fügen Sie Ihrem HTML-Code ein leeres beliebiges Element hinzu, das in einem anderen Modus als im Hochformat "display: none" enthält. - Erstellen Sie einen JQuery- oder Javascript-Listener für die Eingabe: focus. Wenn Sie auf eine Eingabe klicken, überprüft Ihr Javascript die Anzeigeeigenschaft des beliebigen Elements. Wenn "Block" zurückgegeben wird oder was auch immer Sie im Hochformat festgelegt haben, können Sie Ihr Styling mit JS für Ihre Abfragen im Hochformatmodus überschreiben. Umgekehrt hätten Sie eine Eingabe: Blur Listener, um die style.cssText-Eigenschaften der Elemente, die Sie fest codiert haben, auszublenden.

Ich experimentiere gerade selbst damit - ich werde Code veröffentlichen, was funktioniert, wenn ich etwas Festes und Verwaltbares bekomme. (Meine erste Lösung scheint die vernünftigste zu sein).

user3718546
quelle
0

Das funktioniert bei mir zuverlässig. Ich verwende http://detectmobilebrowsers.com/ für die jQuery-Erweiterung, um $ .browser.mobile zu erkennen.

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;

Hier ist mein Code zum Ändern des Ansichtsfensters basierend auf der Ausrichtung. Diese Funktion wird nur für mobile Geräte aufgerufen, nicht einmal für Tablets. Dadurch kann ich problemlos CSS für 400px und 800px (Portrait vs Landscape) schreiben.

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

Aufgrund der Art meiner Anforderungen konnte ich dies nicht allein in CSS Media-Abfragen tun, da das DOM selbst aufgrund der Ausrichtung geändert werden musste. Leider schreiben Geschäftsleute bei meiner Arbeit Softwareanforderungen, ohne vorher die Entwicklung zu konsultieren.

Chris Fremgen
quelle
0

Ich hatte genau das gleiche Problem mit dem iPad.
dh; Wenn die Softtastatur im Hochformat angezeigt wird, wird das Gerät im Querformat erkannt und Stile für Querformat werden auf den Bildschirm angewendet, was zu einer fehlerhaften Ansicht führt.

Gerätespezifikation

  • Gerät : iPad Mini 4
  • Betriebssystem : iOS 11.2.6
  • Bildschirmauflösung : 1024 x 768

Leider hat diese Lösung für mich nicht funktioniert.

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

Also habe ich eine solche Medienabfrage für meinen Porträtmodus geschrieben.

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

dh; Wenn die Softtastatur angezeigt wird, verringert sich die Bildschirmhöhe, die Bildschirmbreite bleibt jedoch auf 768 Pixel, was dazu führte, dass Medienabfragen den Bildschirm als Querformat erkennen. Daher ist die Umgehung wie oben angegeben.

Jacob Nelson
quelle
0

Da das iPhone 11 Pro Max Viewport 414 x 896 PX groß ist, sollte dies ausreichen, um die Ausrichtung zu gewährleisten: Querformat mit minimaler Breite: 500 Pixel

Ivan Maslov
quelle