webentwicklung-frage-antwort-db.com.de

Medienabfrage für Geräte, die Hover unterstützen

Ich möchte ein separates Verhalten für Browser bereitstellen, die Hover unterstützen (z. B. Desktop-Browser) und solche, die dies nicht tun (z. B. Touchscreen-Geräte). Insbesondere möchte ich einen Hover-Status für Browser angeben, die dies unterstützen, aber nicht für Browser, die dies nicht tun, um zu vermeiden, dass mobile Browser ihn mit zusätzlichen Klicks emulieren, da dies andere Interaktionen auf der Seite unterbricht, indem kein Hover definiert wird Zustand für diese Browser wird dies vermieden.

Ich habe die Funktionen von Interaction Media Queries gelesen und es sieht so aus, als sollte es den Trick tun. Ich könnte etwas tun wie:

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

Laut CanIUse ist es auf allen Browsern verfügbar, die ich unterstützen muss, außer IE11 und Firefox.

Also habe ich mich gefragt, ob ich es andersherum machen könnte - da die Haupt-Touch-Geräte das alles unterstützen, dann negiere ich es:

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

Dies scheint jedoch überhaupt nicht zu funktionieren.

Pseudocode-Beispiel für das, was ich versuche zu tun:

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

Gibt es eine Möglichkeit, diese Arbeit in der beabsichtigten Weise zu machen, oder bin ich auf dem falschen Weg?

18
moogal

Dank Dekels Anmerkungen konnte ich dies lösen, indem ich die Logik in JS ausführte und stattdessen eine Klasse anwendete:

z.B.

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

Dann im Stylesheet:

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

Ich habe dies auf Desktop Chrome, Safari und Firefox und iOS Safari getestet und funktioniert wie erwartet.

7
moogal

not sollte den Medientyp (Bildschirm, Druck, alle usw.) und keine Medienfunktion (Schwebeflug, Punkt usw.) voranstellen.

Falsch:

@media not (hover: none)

Richtig:

@media not all and (hover: none)

Ja, es ist nicht intuitiv und komisch. Quelle (siehe Kommentare) .

Sie benötigen also kein Javascript, um das Ergebnis der Medienabfrage zu ändern.

27
artin

Aus den Spezifikationen:

none 

Gibt an, dass das primäre Zeigensystem nicht schweben kann oder dass kein Zeigensystem vorhanden ist. Beispiele sind Touchscreens und Bildschirme, die einen Zeichenstift verwenden.
Zeigersysteme, die schweben können, für die dies jedoch unbequem ist und nicht zur normalen Verwendung gehört, passen ebenfalls zu diesem Wert. 

Zum Beispiel würde ein Touchscreen, auf dem ein langer Druck als schwebend behandelt wird, mit dem Schwebeflug übereinstimmen: none.

Wenn Ihr Browser (Mobil/Touch) lange unterstützt, um den Hover zu simulieren, funktioniert hover: none nicht. Sie können einfach einen Standardwert verwenden und ihn überschreiben (mit Vorrang der Standard-CSS):

body {
    background: red;
}

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

Desktop hat blue Hintergrund und Mobile/Touch hat red Hintergrund

Überprüfen Sie das folgende Beispiel:
https://jsfiddle.net/mcy60pvt/1/

Um die Langdruck-Option des Handys zu überprüfen, können Sie dieses Beispiel verwenden:
https://jsfiddle.net/mcy60pvt/3/

Im obigen Beispiel hat der grüne Block eine :hover-Definition für Desktop und Mobile, jedoch ändert sich der Hintergrund für Desktop auf yellow und für Mobile (bei längerem Drücken) ändert sich dies zu white.

Hier ist die CSS für das letzte Beispiel:

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

In diesem Beispiel - Browser, die :hover nicht unterstützen, werden das Feld hover me mit grünem Hintergrund angezeigt. Wenn Sie "hover" (berühren/lang drücken), wird der Hintergrund weiß.

aktualisieren

Wie für den hinzugefügten Pseudocode:

.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 */
    }
}
11
Dekel

Laut Artins Antwort können wir nur Geräte ansprechen, die Schwebeflug mit reinem CSS unterstützen, mit @media not all and (hover: none). Es sieht komisch aus, aber es funktioniert.

Ich habe daraus ein Sass-Mixin für die einfachere Verwendung gemacht:

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

Folgendes würde die Hintergrundfarbe von .container für Geräte, die Hover unterstützen, von rot zu blau ändern, für Touch-Geräte keine Änderung:

.container {
    background-color: red;

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

Sie können dieses Sass-Mixin verwenden, um den Schwebeflug zu stylen. Es wird das empfohlene Ersatz-:active für Touch-Geräte. Funktioniert auf allen modernen Browsern und 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

Um Firefox zu unterstützen (siehe https://bugzilla.mozilla.org/show_bug.cgi?id=1035774 ), müssen Sie möglicherweise einige Regeln zweimal schreiben. Beachten Sie, obwohl in der Frage, die ich hinzugefügt habe, pointer: coarse nicht angegeben ist, unter der Annahme, dass der Zweck dieser Regeln darin besteht, mobile Bildschirme als Ziel festzulegen:

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

Die Kombination von (pointer: coarse) and (hover: none) sollte für mobile Geräte sinnvoller werden, wenn mobile Bildschirme größer werden und die Korrelation zwischen den Pixelabmessungen und dem mobilen Vergleich mit dem Desktop verloren geht (wenn Sie zwischen Tablet und Desktop unterscheiden möchten).

0
EoghanM