Signatur
Beschreibung
window.matchMedia() ist das JavaScript-Gegenstück zu CSS-@media-Regeln. Die Methode nimmt eine Media Query wie "(max-width: 600px)" oder "(prefers-color-scheme: dark)" entgegen und gibt ein MediaQueryList-Objekt zurück. Dessen Eigenschaft matches sagt, ob die Bedingung jetzt gerade erfüllt ist.
Richtig nützlich wird das durch das change-Event der MediaQueryList: Es feuert nur dann, wenn sich das Ergebnis der Abfrage ändert, also zum Beispiel beim Überschreiten eines Breakpoints oder wenn der Nutzer das Farbschema des Systems umstellt. Das ist deutlich sparsamer als ein resize-Listener, der bei jedem Pixel feuert und in dem man selbst innerWidth vergleichen muss.
Typische Einsatzfälle:
- Responsives Verhalten in JavaScript, etwa ein mobiles Menü oder unterschiedliche Komponenten je nach Breakpoint
- Benutzereinstellungen abfragen:
prefers-color-scheme,prefers-reduced-motion,prefers-contrast - Geräteeigenschaften erkennen:
(pointer: coarse),(hover: hover),(orientation: portrait),print
Breakpoints sollten in CSS und JavaScript identisch sein, sonst weichen Layout und Skriptlogik voneinander ab. Wenn es rein um Styling geht, ist CSS mit @media fast immer die bessere Wahl. matchMedia() braucht man nur, wenn Logik davon abhängt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $mediaQueryString Pflicht | string | Eine Media Query in CSS-Syntax, z. B. "(min-width: 768px)", "screen and (orientation: landscape)" oder "(prefers-reduced-motion: reduce)". Mehrere Abfragen lassen sich mit Komma trennen (logisches ODER). |
Rückgabewert
MediaQueryList-Objekt mit den Eigenschaften matches (boolean) und media (normalisierte Abfrage als string) sowie dem Event change. Bei einer ungültigen Abfrage wird kein Fehler geworfen: media ist dann "not all" und matches ist false.Beispiele
Einmalig prüfen, ob ein mobiler Viewport vorliegt
const mobileQuery = window.matchMedia('(max-width: 600px)');
if (mobileQuery.matches) {
console.log('Mobile Ansicht aktiv');
} else {
console.log('Desktop-Ansicht aktiv');
}
console.log(mobileQuery.media);
Auf Breakpoint-Wechsel reagieren (change-Event)
const desktopQuery = window.matchMedia('(min-width: 1024px)');
const handleLayout = (event) => {
document.body.classList.toggle('layout-desktop', event.matches);
console.log(event.matches ? 'Desktop-Layout' : 'Kompaktes Layout');
};
// Initialzustand setzen – change feuert nicht beim Registrieren
handleLayout(desktopQuery);
desktopQuery.addEventListener('change', handleLayout);
// Später, z. B. beim Entfernen einer Komponente:
// desktopQuery.removeEventListener('change', handleLayout);
Dark Mode des Systems übernehmen und live verfolgen
const darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
const applyTheme = (isDark) => {
document.documentElement.dataset.theme = isDark ? 'dark' : 'light';
console.log(`Theme: ${document.documentElement.dataset.theme}`);
};
applyTheme(darkQuery.matches);
darkQuery.addEventListener('change', (e) => applyTheme(e.matches));
Animationen bei reduzierter Bewegung abschalten (mit AbortController)
const controller = new AbortController();
const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: motionQuery.matches ? 'auto' : 'smooth'
});
};
motionQuery.addEventListener(
'change',
(e) => console.log('Reduzierte Bewegung:', e.matches),
{ signal: controller.signal }
);
scrollToTop();
// Alle Listener auf einmal entfernen:
// controller.abort();
// Wichtig · Fallstricke
- Kein Initial-Event:
changefeuert nur bei einer Änderung. Den Anfangszustand muss man selbst übermatchesauswerten. - Veraltete API:
MediaQueryList.addListener()undremoveListener()gelten als veraltet. VerwendeaddEventListener('change', …). Das ältere Safari vor Version 14 kennt nuraddListener(). Wer das noch unterstützen muss, prüft vorhertypeof mql.addEventListener === 'function'. - Ungültige Abfragen scheitern stumm: Ein Tippfehler wie
"max-width: 600px"ohne Klammern wirft keinen Fehler, sondern liefertmedia === "not all"undmatches === false. Zum Debuggenmql.mediaprüfen. - Einheiten:
pxin Media Queries bezieht sich auf CSS-Pixel, nicht auf Gerätepixel.emrichtet sich nach der Standard-Schriftgröße des Browsers, nicht nach dem Root-Element. - Speicherlecks vermeiden: In Single-Page-Apps und Frameworks Listener beim Unmount entfernen, zum Beispiel über
removeEventListeneroder einAbortSignal. DasMediaQueryList-Objekt am besten einmal erzeugen und wiederverwenden. - Server-Side Rendering: In Node.js und beim SSR gibt es kein
window. Den Zugriff deshalb absichern:typeof window !== 'undefined'. - Datenschutz: Einige Browser verallgemeinern bestimmte Media Features (z. B.
resolution) gegen Fingerprinting. Die Ergebnisse können daher ungenauer sein.