web-dev-qa-db-ja.com

CSS Media Query-ソフトキーボードがCSSの方向規則を破る-代替ソリューション?

複数のタブレットデバイスで作業しています-両方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 */
}

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

デモページから取得した動作のスクリーンショットを次に示します。 enter image description here

したがって、この問題を解決するための代替手段はありますか?ネイティブの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; }

これについてどう思いますか?より良い解決策はありますか?

72
Hossain Khan

私はこれが数年遅れていることを知っていますが、素晴らしい解決策を見つけました

ランドスケープメディアの場合:

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

ポートレートメディアの場合:

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

完全なソリューションとそれが機能する理由については、こちらをご覧ください Michael Barret-Android browser challenges

編集:このリンクの有効期限は切れていますが、スナップショットはインターネットアーカイブで見つけることができます: Michael Barret-Android browser challenges

91
Sean Routledge

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

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

クエリは方向をサポートするデバイス/ユーザーエージェントに限定されないため、このアプローチは方向よりも柔軟です。方向は言うまでもなく telles yo 対幅。

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

27
scurker

代わりに 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を使用すると、更新が実際の方向の変更に制限されます。

12
muru

上記のオプションを試しましたが、問題を解決するものはありませんでした。 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);
6
Robby Jennings

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

  @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以上を報告している場合でも、Landscapeモードの特定の設定を宣言していないので、Androidデバイスの場合はmax-device-aspect-ratioによってポートレートモードがトリガーされますそのように指向されています。

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

2
Helvecio Neto

上記のいくつかの答えを試してみましたが、どれも私が望んでいたことを正確に実行できませんでした。以下は、私が現在生産しているものです。

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

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
therebelrobot

IPadでもまったく同じ問題に直面しました。
ie;ソフトキーボードがポートレートモードで表示されると、デバイスは横向きで検出され、横向きのスタイルが画面に適用され、混乱したビューになります。

デバイス仕様

  • デバイス: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 */
}

すなわち;ソフトキーボードが表示されると、画面の高さは減少しますが、画面の幅は768pxのままであるため、メディアクエリは画面を横向きとして検出します。したがって、上記の回避策が提供されます。

0
Jacob Nelson

これは私にとって確実に機能します。 $ .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(Portrait vs Landscape)の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 Mediaクエリだけでこれを行うことはできませんでした。残念ながら、私の仕事では、ビジネスの人々は最初に開発に相談することなくソフトウェア要件を書きます。

0
Chris Fremgen

次のリンクをご覧ください: http://www.alistapart.com/articles/a-pixel-identity-crisis/
方向だけでなく、max-device-heightまたはdevice-pixel-ratioにも依存すると役立つ場合があります。とにかく、私はそれをテストしなかったので、それが役立つかどうかはわかりません。

0
Sergiy T.

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

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

私は今、これを自分で実験しています-しっかりした管理しやすいものが得られたときに機能するコードを投稿します。 (私の最初の解決策が最も合理的だと思われます)。

0
user3718546