Arbeiten mit JavaScript-Media Queries

Avatar of Marko Ilic
Marko Ilic am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

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

ChromeFirefoxIEEdgeSafari
9610125.1

Mobil / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
12712735.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.

Das ist eine Steigerung der Skripte um 157 %!

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

Das sind 208 Resize-Ereignisse gegenüber sechs übereinstimmenden Media-Ereignissen.

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.