webentwicklung-frage-antwort-db.com.de

CSS Media Query - Soft-Tastatur bricht CSS-Orientierungsregeln - alternative Lösung

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

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

Die einfachste Möglichkeit, einen geräteorientierten Stil anzuwenden, ist die Ausrichtung der Medienabfrage mithilfe der folgenden Syntax.

@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 Soft-Tastatur eingeblendet. Dadurch wird der sichtbare Bereich der Webseite reduziert und das Rendern erzwungen in Landschafts-Css. Auf Android-Tablet-Geräten hängt es von der Höhe der Tastatur ab ... __ So sieht die Webseite letztendlich kaputt aus. Daher kann ich die Orientierungsmedienabfrage von CSS3 nicht verwenden, um Formatvorlagen 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 vollständige Testseite verwenden - http://jsfiddle.net/S5nYP/embedded/result/

Hier ist ein Screenshot des Verhaltens von der Demoseite .enter image description here

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 Schnipsel gefunden, der vorschlägt, auf dieser Basis eine Klasse und ein Ziel hinzuzufügen. Zum Beispiel:

<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 denkst du darüber? Hast du eine bessere Lösung? 

69
Hossain Khan

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 sie funktioniert, finden Sie hier Michael Barret - Herausforderungen für Android-Browser

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

85
Sean Routledge

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

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

Die Medienorientierung "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, führt die Soft-Tastatur offensichtlich dazu, dass sich die Ausrichtung ändert, da die Breite des Ansichtsfensters geringer als die Höhe ist. Eine Lösung wäre, nur Ihre Medienabfragen zu verwenden, die nur auf width basieren. Dies macht es für Geräte unabhängig von der Ausrichtung flexibler. Ganz zu schweigen davon, dass Breite/Höhe stärker unterstützt wird als die Ausrichtung.

Wenn Sie die Breite statt der Orientierung 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 Orientierung, da die Abfragen nicht auf Geräte/Benutzeragenten beschränkt sind, die die Orientierung unterstützen, ganz zu schweigen davon, dass die Orientierung Ihnen sehr wenig sagt gegenüber der Breite.

Natürlich, wenn Sie wirklich Orientierung wissen müssen, scheint es, als würde die Klasse anfangs festgelegt, und verwenden Sie einfach diese Option.

26
scurker

Eine Alternative könnte die Verwendung von device-aspect-ratio sein, 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 aufgrund eines Fehlers , aber ich kann keinen Fehlerbericht finden. Die Verwendung einer Kombination aus orientation und {min,max}-device-aspect-ratio scheint 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 orientation löst erwartungsgemäß Aktualisierungen aus, und die Verwendung von device-aspect-ratio beschränkt sich auf die Aktualisierungsänderungen.

12
muru

Ich habe die oben aufgeführten Optionen durchgearbeitet und keine hat die Probleme für mich behoben. Ich habe zur Verwendung von screen.availHeight gewechselt, da dies zu konsistenten Höhenergebnissen führt, wodurch das Problem der Tastaturanzeige vermieden wird. 

// 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);
6
Robby Jennings

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-ratio für die Auslösung des Portrait-Modus sorgt, indem einfach die Fenstergröße geändert wird (nützlich für PCs und andere Querformatgeräte), hilft max-device-aspect-ratio bei Smartphones oder anderen Geräten mit variabler Ausrichtung. Und da ich keine spezifischen Einstellungen für den Querformat-Modus deklariere, wird der Portrait-Modus auch dann von max-aspect-ratio ausgelöst, wenn max-device-aspect-ratio> 1 an das System meldet. 

Der 1/1-Teil bedeutet im Wesentlichen, dass bei einem Verhältnis <= 1 der Portrait-Modus gewählt wird, andernfalls der Querformat-Modus.

2
Helvecio Neto

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

Zu diesem Zweck werden Fensterbreite und -höhe des Geräteansichtsfensters einem Datenattribut für die spätere Überprüfung zugewiesen. Da die Breite der Telefone beim Hochziehen der Tastatur nicht geändert wird, können Sie nur anhand der Höhe feststellen, ob das Verhältnis UND die Breite mit der Originalbreite verglichen werden, um festzustellen, ob die Tastatur oben ist. Ich habe keinen Anwendungsfall gefunden, der noch nicht ausgefallen ist, aber ich bin mir sicher, dass ich dies tun werde. Wenn Sie alle eine finden, lass es mich wissen.

Ich verwende einige Globals wie InitialRun und MobileOrientation, die für js wechseln verwendet werden. Ich verwende auch html5-Datenattribute, um Informationen im DOM für die Manipulation von CSS 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'});
            }
        }

    }
1
therebelrobot

Ich habe genau das gleiche Problem auf dem iPad.
dh; Wenn die Softtastatur im Hochformat angezeigt wird, wird das Gerät im Querformat erkannt und die Stile für das Querformat werden auf den Bildschirm angewendet, wodurch die Ansicht beeinträchtigt wird.

Gerätespezifikation

  • Gerät: iPad Mini 4 
  • OS: 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 */}

Was ich also getan habe, ist, dass ich eine solche Medienanfrage für meinen Porträtmodus geschrieben habe.

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

dh; Wenn die Soft-Tastatur angezeigt wird, verringert sich die Bildschirmhöhe, aber die Bildschirmbreite bleibt auf 768px, was dazu führt, dass der Bildschirm für die Medienabfrage als Querformat erkannt wird. Daher die Arbeit wie oben angegeben.

0
Jacob Nelson

Das funktioniert zuverlässig für mich. Ich benutze 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 Darstellungsbereichs basierend auf der Ausrichtung. Diese Funktion wird nur für mobile Geräte aufgerufen, nicht einmal für Tablets. Dies ermöglicht mir das einfache Schreiben von CSS für 400px und 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");
}

Aufgrund meiner Anforderungen konnte ich dies nicht allein in CSS Media-Abfragen tun, da sich das DOM aufgrund der Ausrichtung ändern musste. Leider schreiben Geschäftsleute in meinem Job Softwareanforderungen, ohne vorher die Entwicklung von Beratern zu planen.

0
Chris Fremgen

Schauen Sie sich diesen Link an: http://www.alistapart.com/articles/a-pixel-identity-crisis/
Es kann hilfreich sein, sich nicht nur auf die Orientierung zu verlassen, sondern auch auf max-device-height oder device-pixel-ratio. Wie auch immer, ich habe es nicht getestet, also nicht sicher, dass es helfen wird. 

0
Sergiy T.

Idee: Nehmen Sie den Portrait-Parameter von Ihrer Medienabfrage und lassen Sie ihn nur mit einer minimalen Breite. Führen Sie Ihre normale Formatierung für den Hochformatmodus in dieser Medienabfrage durch. Erstellen Sie anschließend eine weitere Medienabfrage für den Querformatmodus mit einer Mindesthöhe, die so groß ist, dass der Browser diese Abfrage nicht verwendet, wenn die Tastatur angezeigt wird. Sie müssten damit experimentieren, was diese "hohe Höhe" ausmacht, aber es sollte nicht zu schwer sein, da die meisten (wenn nicht alle) Landschaftsmodi eine größere Höhe haben, als wenn eine Tastatur aufspringt. Außerdem können Sie der Querformatabfrage eine Mindestbreite hinzufügen, die größer ist als die der meisten Smartphones in der Hochformatansicht (d. H. Ca. 400 px), um den Umfang der Abfrage einzuschränken.

Hier ist eine alternative (und schwierige) Lösung: - Fügen Sie Ihrem HTML-Code ein leeres beliebiges Element hinzu, das "display: none" in einem anderen Modus als im Portrait-Modus hat - Erstellen Sie einen jquery- oder javascript-Listener für Eingabe: focus . Wenn Sie auf eine Eingabe klicken, überprüft Ihr Javascript die Anzeigeeigenschaften des beliebigen Elements. Wenn es "blockiert" oder was auch immer Sie im Hochformatmodus festlegen, zurückgibt, können Sie Ihr Styling mit JS in den Abfragen im Hochformatmodus überschreiben. Umgekehrt hätten Sie eine Eingabe: Verwischen Sie den Listener, um die style.cssText -Eigenschaften der Elemente auszublenden, die Sie hartcodiert haben.

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

0
user3718546