web-dev-qa-db-ja.com

ホバーをサポートするデバイスのメディアクエリ

ホバーをサポートするブラウザー(デスクトップブラウザーなど)とサポートしないブラウザー(タッチスクリーンデバイスなど)に別々の動作を提供したいと思います。具体的には、それをサポートするブラウザーではホバー状態を宣言しますが、サポートしていないブラウザーではホバー状態を宣言しますこれらのブラウザの状態は回避されます。

Interaction Media Queries 機能を読んでみたところ、うまくいくはずです。私は次のようなことができます:

@media (hover: none) {
  /* behaviour for touch browsers */
}

CanIUse によれば、IE11とFirefoxを除く、サポートする必要があるすべてのブラウザーで利用可能です。

だから私は他の方法でそれを行うことができるかどうか疑問に思った-メインのタッチデバイスはすべてそれをサポートしているので、それを否定する:

@media not (hover: none) {
  /* behaviour for desktop browsers */
}

ただし、これはまったく機能しないようです。

私がやろうとしていることの擬似コードの例:

.myelement {
  /* some styling */
  /* note: no hover state here */
}
@media(this device supports hover) {
  .myelement:hover {
    /* more styling */
  }
}

それで、この仕事を意図した方法で行う方法はありますか、それとも間違った方向に進んでいますか?

26
moogal

Dekelのコメントのおかげで、JSでロジックを実行し、代わりにクラスを適用することでこれを解決しました。

例えば.

const canHover = !(matchMedia('(hover: none)').matches);
if(canHover) {
  document.body.classList.add('can-hover');
}

次に、スタイルシートで:

.myElement {
  background: blue;
}
.can-hover .myElement:hover {
  background: red;
}

これをデスクトップのChrome、Safari、Firefox、iOS Safariでテストしましたが、期待どおりに動作します。

7
moogal

notは、メディア機能(ホバー、ポイントなど)ではなく、メディアタイプ(screen、print、allなど)の前に付ける必要があります。

違う:

@media not (hover: none)

正しい:

@media not all and (hover: none)

はい、その直感的で奇妙な。 ソース(コメントを参照)

したがって、メディアクエリの代替結果にJavaScriptは必要ありません。

35
artin

仕様から:

none

プライマリポインティングシステムがホバーできないか、ポインティングシステムがないことを示します。例には、タッチスクリーンや描画スタイラスを使用する画面が含まれます。
ホバリングできるポインティングシステムは、ホバリングは不便であり、通常の使用方法の一部ではないため、この値にも一致します。

たとえば、長押しがホバーリングとして扱われるタッチスクリーンは、ホバーと一致します:none。

ブラウザ(モバイル/タッチ)が長押しをサポートしてホバーをシミュレートしている場合、hover: noneの使用は機能しません。できることは、デフォルト値を使用し、それをオーバーライドするだけです(デフォルトのcss優先度で):

body {
    background: red;
}

@media (hover: hover) {
  body {
    background: blue;
  }
}

デスクトップにはblue背景があり、モバイル/タッチにはred背景があります。

次の例を確認してください。
https://jsfiddle.net/mcy60pvt/1/

モバイルの長押しオプションを確認するには、次の例を使用できます。
https://jsfiddle.net/mcy60pvt/3/

上記の例では、緑色のブロックにはデスクトップとモバイルの両方の:hover定義がありますが、デスクトップの背景はyellowに変わり、モバイル(長押し)の場合はwhiteに変わります。

最後の例のcssは次のとおりです。

body {
    background: red;
}
div.do-hover {
  border: 1px solid black;
  width: 250px;
  height: 250px;
  background: green;
}
div.do-hover:hover {
  background: white;
}

@media (hover: hover) {
  body {
    background: blue;
  }
  div.do-hover:hover {
    background: yellow;
  }
}

この例では、:hoverをサポートしていないブラウザは、緑の背景でhover meボックスを表示し、「hover」(タッチ/長押し)している間-背景が白に変わります。

更新

追加された擬似コードに関して:

.myelement {
    /* some styling #1 */
    /* note: no hover state here */
}
@media(hover: hover) {
    .myelement {
        /* some styling that override #1 styling in case this browser suppot the hover*/
    }
    .myelement:hover {
        /* what to do when hover */
    }
}
14
Dekel

Artin´s answer によれば、@media not all and (hover: none)を使用して、純粋なcssでホバーをサポートするデバイスのみに対処できます。変に見えますが、動作します。

使いやすくするために、これからSassミックスインを作成しました。

@mixin hover-supported {
    @media not all and (hover: none) {
        &:hover {
            @content;
        }
    }
}

以下は、ホバーをサポートするデバイスのホバーで.containerの背景色を赤から青に変更します。タッチデバイスは変更しません。

.container {
    background-color: red;

    @include hover-supported() {
        background-color: blue;
    }
}
0
Calsal

このSassミックスインを使用してホバーのスタイルを設定できます。推奨される代替:activeタッチデバイス用。最新のすべてのブラウザーとIE11で動作します。

/**
 Hover styling for all devices and browsers
 */
@mixin hover() {
    @media (hover: none) {
        &:active {
            @content;
        }
    }

    @media (hover: hover), all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
        &:hover {
            @content;
        }
    }
}

.element {
    @include hover {
         background: red;
    }
}
0

Firefoxをサポートするには( https://bugzilla.mozilla.org/show_bug.cgi?id=1035774 を参照)、潜在的にいくつかのルールを2回記述する必要があります。これらのルールの目的はモバイル画面をターゲットにすることであるという前提で、pointer: coarseを追加した質問では指定されていませんが、注意してください。

/* BEGIN devices that DON'T pinch/zoom */
/* If https://bugzilla.mozilla.org/show_bug.cgi?id=1035774 
is fixed then we can wrap this section in a ...
@media not all and (pointer: coarse) and (hover: none) {
.. and do away with the 'NEGATE' items below */

.myelement {
  /* some styling that you want to be desktop only (style as an anchor on desktop) */
  font-size: 14px;
  text-decoration: underline;
  border: none;
}
/* END devices that DON'T pinch/zoom */

/* BEGIN devices that DO pinch/zoom */   
@media (pointer: coarse) and (hover: none) {
  .myelement {
    /* style as a large button on mobile */
    font-size: inherit;  /* maintain e.g. larger mobile font size */
    text-decoration: none;  /* NEGATE */
    border: 1px solid grey;
  }

  .myelement:hover {
    /* hover-only styling */
  }
}
/* END devices that DO pinch/zoom */

(pointer: coarse) and (hover: none)の組み合わせは、モバイル画面が大きくなり、ピクセルサイズとモバイルとデスクトップの相関関係が失われるため、モバイルデバイスをターゲットとするのに役立つはずです(すでにタブレットとデスクトップを区別したい場合)

0
EoghanM