Signatur
Beschreibung
Das Ereignis change wird auf einem MediaQueryList-Objekt ausgelöst, das Sie mit window.matchMedia() erzeugt haben. Es feuert immer dann, wenn die Media Query neu ausgewertet wird und sich das Ergebnis dadurch ändert, zum Beispiel wenn das Fenster eine Breitengrenze überschreitet, das Gerät gedreht wird oder die Person im Betriebssystem zwischen hellem und dunklem Farbschema wechselt.
Der Handler bekommt ein MediaQueryListEvent mit den Eigenschaften matches (der neue boolesche Zustand) und media (die serialisierte Query als String). Sie können ihn mit addEventListener("change", handler) registrieren oder über die Eigenschaft onchange zuweisen.
Gegenüber einem resize-Listener ist das Ereignis deutlich effizienter: Es feuert nur beim tatsächlichen Wechsel des Zustands und nicht bei jedem Pixel. Damit eignet es sich gut für JavaScript-Logik, die zu CSS-Breakpoints passen soll, für Dark-Mode-Umschaltung, prefers-reduced-motion oder für die Erkennung von Druckansicht und Ausrichtung.
Wichtig: Beim Registrieren wird das Ereignis nicht sofort ausgelöst. Den Anfangszustand müssen Sie selbst über mql.matches abfragen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname, hier immer "change". |
|
| $handler Pflicht | (event: MediaQueryListEvent) => void | Callback, der bei jedem Zustandswechsel aufgerufen wird. event.matches enthält den neuen Zustand, event.media die Query. |
|
| $options | boolean | AddEventListenerOptions | false | Die üblichen Optionen von addEventListener, z. B. { once: true } oder { signal } zum Entfernen per AbortController. |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler bekommt ein MediaQueryListEvent.Beispiele
Responsives Verhalten per addEventListener
const mql = window.matchMedia("(max-width: 768px)");
const applyLayout = (isMobile) => {
document.body.classList.toggle("mobile-nav", isMobile);
console.log(isMobile ? "Mobil-Layout aktiv" : "Desktop-Layout aktiv");
};
// Anfangszustand selbst setzen, denn change feuert nicht beim Registrieren
applyLayout(mql.matches);
mql.addEventListener("change", (event) => {
applyLayout(event.matches);
});
Dark Mode des Systems verfolgen (onchange-Property)
const darkQuery = window.matchMedia("(prefers-color-scheme: dark)");
const setTheme = (dark) => {
document.documentElement.dataset.theme = dark ? "dark" : "light";
};
setTheme(darkQuery.matches);
darkQuery.onchange = (event) => {
setTheme(event.matches);
console.log(`Theme gewechselt: ${event.media} -> ${event.matches}`);
};
Listener wieder entfernen (removeEventListener und AbortController)
const motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
const onMotionChange = (event) => {
console.log("Reduzierte Bewegung:", event.matches);
};
motionQuery.addEventListener("change", onMotionChange);
// später, z. B. beim Unmount einer Komponente:
motionQuery.removeEventListener("change", onMotionChange);
// Alternative: mehrere Listener auf einmal über ein Signal entfernen
const controller = new AbortController();
const printQuery = window.matchMedia("print");
printQuery.addEventListener("change", (e) => console.log("Druck:", e.matches), {
signal: controller.signal,
});
controller.abort(); // Listener ist entfernt
// Wichtig · Fallstricke
- Kein Initialaufruf:
changefeuert erst beim ersten Wechsel. Den Startzustand müssen Sie immer übermql.matchesauswerten. - Veraltete API:
mql.addListener(fn)undmql.removeListener(fn)gelten als veraltet. Safari vor Version 14 unterstützt nur diese Variante, dort warMediaQueryListnoch keinEventTarget. Wenn Sie ältere Browser unterstützen müssen, prüfen Sie vorher:if (mql.addEventListener) { … } else { mql.addListener(fn); }. - Referenz behalten: Rufen Sie
matchMedia()einmal auf und speichern Sie das Objekt. Ein zweiter Aufruf liefert ein neues Objekt, auf dem der Listener nicht registriert ist.removeEventListenerfunktioniert außerdem nur mit derselben Funktionsreferenz. - Nur Zustandswechsel: Das Ereignis meldet ausschließlich einen Wechsel von
matches, keine Größenänderungen innerhalb eines Bereichs. Für stufenlose Werte brauchen Sieresizeoder denResizeObserver. - In iframes und bei Zoom werden Media Queries relativ zum jeweiligen Viewport ausgewertet. Durch Browser-Zoom kann das Ereignis deshalb ebenfalls feuern.