Was fällt Ihnen als Erstes ein, wenn Sie an Media Queries denken? Vielleicht etwas in einer CSS-Datei, das so aussieht
body {
background-color: plum;
}
@media (min-width: 768px) {
body {
background-color: tomato;
}
}
CSS-Media-Queries sind eine Kernkomponente jedes responsiven Designs. Sie sind eine hervorragende Möglichkeit, verschiedene Stile auf verschiedene Kontexte anzuwenden, sei es basierend auf der Ansichtsfenstergröße, der Bewegungsvoreinstellung, dem bevorzugten Farbschema, spezifischen Interaktionen und sogar bestimmten Geräten wie Druckern, Fernsehern und Projektoren, unter vielen anderen.
Aber wussten Sie, dass es Media Queries auch für JavaScript gibt? Das stimmt! Wir sehen sie in JavaScript vielleicht nicht so oft, aber es gibt definitiv Anwendungsfälle dafür, die ich im Laufe der Jahre für die Erstellung responsiver Plugins wie Slider als hilfreich empfunden habe. Beispielsweise müssen Sie bei einer bestimmten Auflösung möglicherweise die Slider-Elemente neu zeichnen und neu berechnen.
Die Arbeit mit Media Queries in JavaScript unterscheidet sich stark von der Arbeit mit ihnen in CSS, auch wenn die Konzepte ähnlich sind: stimme einige Bedingungen ab und wende einige Dinge an.
matchMedia() verwenden
Um in JavaScript zu bestimmen, ob das Dokument mit der Media-Query-Zeichenfolge übereinstimmt, verwenden wir die Methode matchMedia(). Obwohl sie offiziell Teil der CSS Object Model View Module-Spezifikation ist, die sich im Working-Draft-Status befindet, ist die Browserunterstützung dafür hervorragend und reicht bis zu Internet Explorer 10 mit 98,6 % globaler Abdeckung zurück.
Diese Browser-Supportdaten stammen von Caniuse, das mehr Details enthält. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version und aufwärts unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 9 | 6 | 10 | 12 | 5.1 |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 3 | 5.0-5.1 |
Die Verwendung ist nahezu identisch mit CSS-Media-Queries. Wir übergeben die Media-Query-Zeichenfolge an matchMedia() und überprüfen dann die .matches-Eigenschaft.
// Define the query
const mediaQuery = window.matchMedia('(min-width: 768px)')
Die definierte Media-Query gibt ein MediaQueryList-Objekt zurück. Dies ist ein Objekt, das Informationen über die Media-Query speichert, und die wichtigste Eigenschaft, die wir benötigen, ist .matches. Dies ist eine schreibgeschützte boolesche Eigenschaft, die true zurückgibt, wenn das Dokument mit der Media-Query übereinstimmt.
// Create a media condition that targets viewports at least 768px wide
const mediaQuery = window.matchMedia('(min-width: 768px)')
// Check if the media query is true
if (mediaQuery.matches) {
// Then trigger an alert
alert('Media Query Matched!')
}
Das ist die grundlegende Verwendung zum Abgleichen von Medienbedingungen in JavaScript. Wir erstellen eine Übereinstimmungsbedingung (matchMedia()), die ein Objekt (MediaQueryList) zurückgibt, prüfen dagegen (.matches) und tun dann etwas, wenn die Bedingung als wahr ausgewertet wird. Gar nicht so unähnlich wie CSS!
Aber es steckt noch mehr dahinter. Wenn wir beispielsweise die Fenstergröße *unterhalb* unserer Zielgröße ändern, aktualisiert sich nichts von selbst, wie es bei CSS der Fall wäre. Das liegt daran, dass .matches für einmalige sofortige Überprüfungen perfekt ist, aber keine kontinuierliche Überprüfung auf Änderungen ermöglicht. Das bedeutet, wir müssen...
Auf Änderungen hören
MediaQueryList verfügt über eine addListener() (und die anschließende removeListener())-Methode, die eine Callback-Funktion (repräsentiert durch das .onchange-Ereignis) akzeptiert, die aufgerufen wird, wenn sich der Status der Media-Query ändert. Mit anderen Worten, wir können zusätzliche Funktionen auslösen, wenn sich die Bedingungen ändern, sodass wir auf die aktualisierten Bedingungen „reagieren“ können.
// Create a condition that targets viewports at least 768px wide
const mediaQuery = window.matchMedia('(min-width: 768px)')
function handleTabletChange(e) {
// Check if the media query is true
if (e.matches) {
// Then log the following message to the console
console.log('Media Query Matched!')
}
}
// Register event listener
mediaQuery.addListener(handleTabletChange)
// Initial check
handleTabletChange(mediaQuery)
Das One-Two-Punch von matchMedia() und MediaQueryList gibt uns die gleiche Leistung, um nicht nur Medienbedingungen abzugleichen, die CSS bietet, sondern auch aktiv auf aktualisierte Bedingungen zu reagieren.
Wenn Sie einen Ereignis-Listener mit addListener() registrieren, wird er zunächst nicht ausgelöst. Wir müssen die Ereignis-Handler-Funktion manuell aufrufen und die Media-Query als Argument übergeben.
Der alte Weg, Dinge zu tun
Um den Kontext zu geben – und ein wenig Nostalgie – möchte ich die alte, aber immer noch beliebte Methode abdecken, „Media Queries“ in JavaScript zu machen (und ja, diese Anführungszeichen sind hier wichtig). Der gängigste Ansatz ist das Binden eines resize-Ereignis-Listeners, der window.innerWidth oder window.innerHeight überprüft.
Sie werden so etwas in der Praxis immer noch sehen
function checkMediaQuery() {
// If the inner width of the window is greater then 768px
if (window.innerWidth > 768) {
// Then log this message to the console
console.log('Media Query Matched!')
}
}
// Add a listener for when the window resizes
window.addEventListener('resize', checkMediaQuery);
Da das Resize-Ereignis bei jeder Größenänderung des Browsers aufgerufen wird, ist dies eine kostspielige Operation! Wenn wir uns die Leistungsauswirkungen einer **leeren Seite** ansehen, können wir den Unterschied erkennen.

Eine noch einfachere Möglichkeit, den Unterschied zu erkennen, ist die Hilfe eines Konsolenprotokolls.

Selbst wenn wir die Leistungsprobleme außer Acht lassen, ist Resize restriktiv, da es uns nicht erlaubt, erweiterte Media Queries für Dinge wie Druck und Ausrichtung zu schreiben. Während es also das Verhalten einer „Media Query“ imitiert, indem es uns erlaubt, Ansichtsfensterbreiten abzugleichen, kann es kaum etwas anderes abgleichen – und wir wissen, dass echte Media Queries so viel mehr können.
Fazit
Das ist ein Blick auf Media Queries in JavaScript! Wir haben untersucht, wie matchMedia() uns erlaubt, Medienbedingungen zu definieren, und das MediaQueryList-Objekt untersucht, das uns erlaubt, einmalige (.matches) und dauerhafte (addListener()) Überprüfungen gegen diese Bedingungen durchzuführen, damit wir auf Änderungen reagieren können (.onchange), indem wir Funktionen aufrufen.
Wir haben auch den „alten“ Weg kennengelernt, indem wir auf resize-Ereignisse des Fensters reagiert haben. Obwohl er immer noch weit verbreitet ist und eine völlig legitime Methode ist, um auf Änderungen der Größe von window.innerWidth zu reagieren, kann er keine Überprüfungen für erweiterte Medienbedingungen durchführen.
Um den Artikel hier abzuschließen, hier ist ein nützliches Beispiel, das auf die alte Weise nicht erreichbar ist. Mit einer Media-Query überprüfe ich, ob sich der Benutzer im Querformat befindet. Dieser Ansatz ist beim Entwickeln von HTML5-Spielen üblich und wird am besten auf einem Mobilgerät angezeigt.
Vielen Dank für die Erklärung dieser nützlichen Art, JS-Media-Queries zu verwenden.
Das gefällt mir, ich habe immer die „alte“ Methode verwendet
.match ist nicht notwendig, um einen Boolean zu überprüfen
Wie kann das in React verwendet werden? Ich suche nach einer eleganten Möglichkeit, meine Komponenten responsiv zu machen, ohne CSS zu verwenden. Ich möchte mich nicht als React-Entwickler bezeichnen und immer noch CSS-Media-Queries anstelle von reinem JS verwenden. Bitte äußern Sie sich dazu. Danke
Sie können den
useState-Hook verwenden und die State-Set-Funktion an den Event-Listener binden. Daher wird der Wert bei jeder Änderung gesetzt und der Zustand ist reaktiv. Fügen Sie einfach die anfängliche Prüfung und Einrichtung imuseEffect-Hook hinzu.Nur eine Idee, ich benutze React nicht viel.
Ich bin ein React-Entwickler, aber ich denke immer noch, dass die Verwendung von CSS-Media-Queries anstelle von JS eine bessere Leistung hat, als darauf zu warten, dass der Browser/die Komponente gemountet wird und die Ansichtsfensterbreite/-höhe danach abruft.
Es besteht kein Zweifel daran, was besser ist, sie sollten gar nicht verglichen werden. Dies ist nur eine neue optimierte Möglichkeit, alte Probleme zu lösen, das
resize-Ereignis plus die Überprüfung der Browserbreite.Heute habe ich von Ereignissen erfahren, die mit match media kommen…. danke Amit dafür… Orientation-Medien haben an sich einige Probleme, denke ich… sie funktionieren nicht richtig, wenn die virtuelle Tastatur geöffnet ist....
Das stimmt, leider ist das ein altes CSS-Problem. Hier ist eine Erklärung, warum.
Wenn man sich die vom W3 bereitgestellte Spezifikation ansieht, heißt es:
Spezifikation: https://www.w3.org/TR/css3-mediaqueries/#orientation
Deshalb kann dieses Problem manchmal auftreten. Dies kann durch das Schreiben einer anderen Abfrage verbessert werden, z. B. durch die Verwendung von
min-aspect-ratioBasierend auf Ihrem Beitrag habe ich ein kleines Modul erstellt, das auf gute Weise verwendet werden kann, wie wir es bei der Entwicklung normalerweise benötigen.
https://github.com/bzaman/JavaScript-Media-Queries/blob/master/README.md
Danke für den Artikel. Eine Verbesserung kann hier hinzugefügt werden. Anstatt die spezielle Methode
addListenerzu verwenden, die als veraltet markiert ist, können wir die native Event-Schnittstelle verwenden und sie einfach auf diese Weise einstellen:mediaQuery.addEventListener('change', handleTabletChange).Veraltet wird für
addListeneroft erwähnt, aber tatsächlich ist es das nicht, soweit ich weiß. Selbst wenn man die MDN-Seite prüft, ist es dort nicht als veraltet markiert.Wenn man sich die CSSWG-DOM ansieht, heißt es:
So verwende ich es, im Grunde ein Alias, der abwärtskompatibel ist.
Aber Sie liegen nicht falsch, das Hinzufügen eines Ereignis-Listeners für
changeist das, was tatsächlich passiert, und Ihr Code wird funktionieren.@marco es ist jetzt: https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener#browser_compatibility
Entschuldigung für das Post-Spamming, aber ich habe gerade gesehen, dass
addListenerab IE10 unterstützt wird, währendaddEventListenerauch ab IE9 unterstützt wird, was die Unterstützung tatsächlich zu erweitern scheint.Fehlt mir etwas oder ergibt die Resize-Summe 3498? Guter Artikel aber.
Nun, jemand hat ein scharfes Auge. Gut erkannt. Das liegt daran, dass die Zahlen Fließkommazahlen sind und wir nur ganze Zahlen sehen. Wenn sie summiert wurden, ergab sich eine 1 (vermute ich).
Wie wäre es mit CSS-Variablen? So etwas wie
@media (min-width: 450px) {
:root {
–actualMedia: small;
}
}
und dann den Wert der Variable –actualMedia in JS lesen
if (getComputedStyle(document.documentElement)
.getPropertyValue(‘–actualMedia’)
.trim() === “small”) {
// …
}
Ich habe diese Lösung schon vor einiger Zeit gesehen. Damals war es so etwas wie
body:after {content: "mq-small"und die neue mit CSS Custom Properties ist noch besser, funktioniert aber nicht in IE 11. Aber ich bin mir nicht sicher, welche Lösung aus Leistungssicht besser ist?Vor einiger Zeit habe ich davon erfahren und eine Bibliothek erstellt, die bei der einfachen Verwendung von matchMedia auf allen Geräten hilft. Wenn Sie sie sich ansehen möchten: https://github.com/enmanuelduran/mediaquerysensor
Was ist
ein der Funktion?@Mohammed das ist das Event-Objekt, in diesem Fall das Objekt, das in
mediaQueryzurückgegeben wird.Bei einer Standardverwendung von @media können wir Folgendes tun:
@media only screen and (max-width: 479px) and (orientation: portrait) {
// CSS
}
@media only screen and (min-width: 480px) and (max-width: 768px) {
// CSS
}
@media only screen and (min-width: 769px) and (max-width: 1280px) {
// CSS
}
@media only screen and (min-width: 1281px) and (max-width: 1599px) {
// CSS
}
Kann etwas Ähnliches mit Ihrem „matchMedia“-Ansatz gemacht werden? Ihr Beispiel zeigt nur eine Auflösung (min-width: 768px), sodass ich mich frage, ob dies eine Einschränkung ist. Ich würde gerne wissen, ob das möglich ist. Danke!
Danke für diesen Beitrag, er hat mir heute sehr geholfen.
Ich würde nur ein Update vorschlagen, da „addListener“ veraltet ist.
Mit freundlichen Grüßen und nochmals vielen Dank.