CSSメディアクエリ-ソフトキーボードが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 */
}

これは、すべてのタブレットデバイスで完全に正常に機能します。しかし、問題は、デバイスがポートレートモードで、ユーザーが任意の入力フィールド(検索など)をタップすると、ソフトキーボードがポップアップすることです。これにより、Webページの表示領域が縮小され、ランドスケープベースのCSSでレンダリングされます。Androidタブレットデバイスでは、キーボードの高さに依存します。したがって、最終的にWebページは壊れているように見えます。したがって、CSS3のオリエンテーションメディアクエリを使用して、オリエンテーションに基づいてスタイルを適用することはできません(ターゲットのオリエンテーションに適したメディアクエリがない限り)。これは、これをエミュレートするフィドルhttp://jsfiddle.net/hossain/S5nYP/5/です-デバイステストには、完全なテストページを使用してください-http://jsfiddle.net/S5nYP/embedded/result/

これは、デモページから取得した動作のスクリーンショットです。 ここに画像の説明を入力してください

したがって、この問題に取り組むための代替手段はありますか?ネイティブのCSSベースのソリューションが機能しない場合は、JavaScriptベースのソリューションを利用できます。

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 OS(ハニカムタブレット)と携帯電話のみです。
Hossain Khan

私は自分のモバイルウェブサイトで同様の問題に遭遇しました。いくつかのAndroidデバイスでテストしたところ、特定のOSやモバイル/タブレットデバイスに限定されているようには見えません。主にMotorolaおよびSamsungデバイスの問題のようです。HTC電話で問題を再現できませんでした。
TJ Kirchner 2012

1
この問題は主にAndroidデバイス、モバイル/タブレットで発生します。これを再現する唯一の方法は、高さの高いカスタムキーボードをインストールすることです。これにより、キーボードが表示されているときに、Webビューで使用できる高さが使用可能な幅よりも小さくなります。その場合にのみ、webviewが方向の変更をトリガーします。たとえば、スクリーンショットで、キーボードの上の提案レイヤーを無効にできる場合、Webビューの高さが幅よりも大きくなるため、この問題は発生しません。しかし、とにかく、私はまだエレガントで効率的な解決策を持っていません。
Hossain Khan

1
IOS 7.0.0フルスクリーンWebAppにもこの動作があることを理解してください
Alexandre

それは悲しいです。問題を効率的に解決できなかったため、としてマークを付けました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 */}

完全な解決策とそれが機能する理由はここにありますMichaelBarret-Androidブラウザの課題

編集:このリンクは期限切れになりましたが、スナップショットはインターネットアーカイブにあります:MichaelBarret-Androidブラウザの課題


2
それは問題を解決しますが、私にとって他のデバイス(主にラップトップとコンピューター)でより多くの問題を引き起こします
Stephan Bijzitter 2015

残念ながら、このソリューションはすべてのモバイルデバイスで機能するとは限りません。
Diogo Cardoso 2015

@StephanBijzitter多分あなたは 'max-width'プロパティを使うことができますか?
ショーンラウトレッジ2015

3
このソリューションは非常に大まかなものであり、一部のデバイスでは機能しません。たとえば、私の電話ではソフトキーボードを開いたときに約17.7 / 9が表示されますが、他の多くのデバイスでは横向きのアスペクト比がはるかに低くなっています。
raacer 2015

2
完全なソリューションリンクが壊れています。
Sparkmorry 2018

27

問題は、方向の計算方法にあります。

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

「高さ」メディア機能の値が「幅」メディア機能の値以上の場合、「向き」メディア機能は「ポートレート」です。それ以外の場合、「方向」は「風景」です。

高さ/幅は表示されているビューポートで計算されるため、ビューポートの幅が高さよりも小さいため、ソフトキーボードによって方向が反転するようです。1つの解決策は、メディアクエリを使用することです。width代わりににことです。これにより、向きに関係なくデバイス間でより柔軟になります。もちろん、幅/高さは向きよりも広くサポートされています。

向きではなく幅を考慮したい場合は、例としてiPhoneを使用します。

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

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

クエリはオリエンテーションをサポートするデバイス/ユーザーエージェントに限定されないため、このアプローチはオリエンテーションよりも柔軟性があります。もちろん、オリエンテーション幅に対してほとんど教えてくれません

もちろん、本当に向きを知る必要がある場合は、最初にクラスを設定し、それを使用するのが最善の選択肢のようです。


1
横向きと縦向きがブラウザによってどのように計算されるかを理解しています。しかし、これを処理するための代替のより良い方法が必要です。もう1つの興味深い点は、キーボードが上がっているときにiPadが向きの変更をトリガーしないことです。**** androidがそのように実装しなければならなかった理由はわかりません。
Hossain Khan

幅だけでなく、デバイスの向きが特に必要な理由が気になります。幅だけでは解決しないという、解決しようとしている問題は何ですか?
scurker 2012年

解像度の異なる複数のデバイスを使用しています。向きの代わりに幅を使用する方法の例を教えてください。方向変更の使用については、方向変更に関する複数のアプリケーションがあります。通常、使用可能なスペースは方向によって異なります。そのため、一部の要素は、向きに基づいて非表示にしたり、サイズを変更したりできます。すべての助けをありがとう。
Hossain Khan 2012

@HossainKhan@media all and (max-device-wdith:NNNpx){}または@media all and (min-device-wdith:NNNpx){}または@media all and (device-wdith:NNNpx){}
RaphaelDDL 2012年

1
最終的にand (orientation:portrait)、最大幅と最小幅を削除して適用するだけで、私の問題は解決しました。
Libin 2013年

16

別の方法として、を使用することもできますがdevice-aspect-ratio、これは変更されません。ただし、Webkitでは、JavaScriptテストが新しいアスペクト比に対してtrueを返しても、デバイスを回転しても、このクエリを使用してCSSルールの更新はトリガーされません。これは明らかにバグ原因ですが、バグレポートを見つけることができません。組み合わせを使用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制限を使用すると、実際の方向の変更に更新されます。



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にはバグがあるため、IOSにはwindow.orientationを使用してください。デスクトップでは、画面のサイズではなくウィンドウのサイズが必要なため、window.innerHeight、window.innerWidthを使用する必要があります。
ロビージェニングス

私は上記のコードで壁に頭をぶつけてきました。気難しい。私はこのアプリのデスクトップをサポートしていないので、window.orientationを使用しています。これはAndroidとIOSの魔法のソリューションです。現在は正常に動作しています。var Orientation = Math.abs(window.orientation)=== 90?'風景写真';
ロビージェニングス2012

3

私にとって、これはトリックをしました:

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

しながら、max-aspect-ratio単に(PCおよびその他の風景のみのデバイスのために有用な)ウィンドウのサイズを変更することによってトリガポートレートモードの世話を、max-device-aspect-ratioスマートフォンまたは可変配向を有する他のデバイスに役立ちます。また、ランドスケープモードの特定の設定を宣言していないためmax-aspect-ratio、システムに> 1を報告している場合でも、ポートレートモードは次のコマンドによってトリガーされます。max-device-aspect-ratio場合でも、Androidデバイスがそのように方向付け場合はます。

この1/1部分は基本的に、比率が<= 1の場合はポートレートモードになり、そうでない場合はランドスケープモードになります。


2
キーボードが出てきたらどうですか?
adi518 2018年

仮想キーボードがモバイルデバイスに表示されても、デバイスのアスペクト比(max-device-aspect-ratio)は、実際にデバイスを回転させたとき、または画面の向きを意図的に縦向きから横向きに、またはその逆に変更したときにのみ変化するため、何も変わりません。 -その逆。
helveciofneto 2018年

はい、私はそれを自分で実装してテストすることになりました。私はこれを中心にパッケージを開発しています:npmjs.com/package/mobile-orientation
adi5

もう1つ質問するために戻ってきました:(max-aspect-ratio: 1/1)。デスクトップでポートレートを検出するためにこのビットが必要なだけのようですか?
adi518 2018

正しい。1/1は、完全な正方形が引き続きポートレートモードをトリガーするようにすることです(これは、デスクトップのブラウザーウィンドウのように、ウィンドウのサイズ変更が可能なシステムで可能です)。それがないと、この正確な比率で奇妙なことが起こります。
helveciofneto 2018

1

私は上記のいくつかの答えに目を通しましたが、どれも私が望んでいたこと、つまりiPhoneの機能を可能な限り模倣することを正確に実行しませんでした。以下は、現在本番環境で私のために働いているものです。

これは、将来のチェックのために、デバイスビューポートのウィンドウの幅と高さをデータ属性に割り当てることによって機能します。電話機はキーボードを引き上げたときに幅のサイズを変更しないため、高さだけを確認し、比率と幅を元の幅と比較して、キーボードが上がっているかどうかを確認できます。これが失敗したユースケースはまだ見つかりませんが、きっとそうなると思います。見つけたら教えてください。

jsスイッチングに使用されるInitialRunやMobileOrientationなどのグローバルを使用しています。また、css操作のために情報をDOMに格納するためにhtml5データ属性も使用しています。

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

max-width:896pxはすべてのモバイルデバイスに使用できることがわかりました。それが機能するこのソリューションを試してください!


あなたは私の日を救います:)しかし、それが横向きから縦向きに戻ったとき、ページのズームは壊れていますこれを処理する方法は?
アミールファラハニ

これはモバイルデバイスの現在の最大幅に依存しており、テクノロジーを改善するとこれらは変化します。では、すべてのメディアクエリシナリオを変更する必要がありますか?これは悪い考えだと思います。
QMaster


0

アイデア:メディアクエリからportraitパラメータを削除し、最小幅のみを残します。そのメディアクエリでポートレートモードの通常のスタイリングを行います。次に、キーボードがポップアップしたときにブラウザがそのクエリを使用しないように、最小の高さで横向きモードの別のメディアクエリを作成します。この「十分に高い最小の高さ」を試してみる必要がありますが、ほとんどの(すべてではないにしても)ランドスケープモードの高さは、キーボードがポップアップしたときよりも大きいため、それほど難しくはありません。さらに、横向きのクエリに「最小幅」を追加して、縦向きのビューでほとんどのスマートフォンよりも大きく(つまり、約400px)、クエリの範囲を制限することができます。

代替の(そして希薄な)解決策は次のとおりです。-ポートレートモード以外では「display:none」を持つ空の任意の要素をhtmlに追加します。-input:focusのjqueryまたはjavascriptリスナーを作成します。入力がクリックされると、JavaScriptは任意の要素の表示プロパティをチェックします。'block'またはポートレートモード中に設定したものが返される場合は、JSを使用したスタイリングをポートレートモードのクエリに上書きできます。逆に、ハードコーディングした要素のstyle.cssTextプロパティを空白にするinput:blurリスナーがあります。

私は今これを自分で実験しています-何かがしっかりしていて扱いやすいものになったときに何が機能するかについてのコードを投稿します。(私の最初の解決策が最も合理的なようです)。


0

これは私にとって確実に機能します。$ .browser.mobileを検出するためのjQuery拡張機能にhttp://detectmobilebrowsers.com/を使用しています

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;

これは、向きに基づいてビューポートを変更するための私のコードです。この関数はモバイルデバイスに対してのみ呼び出され、タブレットに対しても呼び出されません。これにより、400pxと800px(ポートレートとランドスケープ)のCSSを簡単に作成できます。

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

要件の性質上、DOM自体を方向に基づいて変更する必要があるため、CSSメディアクエリだけでこれを行うことはできませんでした。残念ながら、私の仕事では、ビジネスマンは最初に開発に相談せずにソフトウェア要件を作成します。


0

私はiPadでもまったく同じ問題に直面しました。
すなわち; ソフトキーボードが縦向きモードで表示されると、デバイスが横向きで検出され、横向きのスタイルが画面に適用されるため、ビューが台無しになります。

デバイス仕様

  • デバイス:iPad Mini 4
  • OS: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 MaxViewportは414x 896 PXであるため、向きを設定するには十分なはずです:横向き、最小幅:500px

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.