The JavaScript side of media queries
Most developers meeting media queries for the first time encounter them in CSS—a block of styles gated behind a viewport width, a color scheme, or even a target device like a printer. But the same matching logic is available to JavaScript through the Window.matchMedia() method, and it opens up some useful possibilities for responsive components that need to recalculate or re-render at different breakpoints.
The API is part of the CSS Object Model View Module specification (currently a Working Draft), yet browser support is excellent, reaching back to Internet Explorer 10 and covering around 98.6% of browsers globally.
Basic matching with matchMedia()
Using matchMedia() in JavaScript mirrors CSS media queries closely. You pass a media query string to the method, and it returns a MediaQueryList object containing information about whether the document matches that query. The key property is .matches, a read-only Boolean that returns true when the document satisfies the conditions.
// Define the query
const mediaQuery = window.matchMedia('(min-width: 768px)')
// 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!')
}
This works fine for one-time checks against the current state of the document. If the window is resized below or above the target condition afterward, nothing updates automatically—.matches is a snapshot, not a live binding. For an immediate answer to "am I in this state right now?", it's perfect. For responding to changes, you need to listen.
Listening for state changes
To keep up with changing conditions, MediaQueryList exposes an addListener() method (with a matching removeListener() for cleanup). It takes a callback function that fires whenever the media query's status flips, using the .onchange event. This gives you the ability to react to condition shifts rather than simply checking them once.
// 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)
One important detail: a listener registered with addListener() won't fire on registration. If you need an immediate invocation alongside the change-triggered ones, you have to call the handler manually, passing the media query in as the argument.
Why the old resize approach falls short
Before matchMedia() saw widespread use, the common workaround for "media queries" in JavaScript was binding a resize listener and reading window.innerWidth or window.innerHeight to decide how to behave. The approach is still fairly common in production code.
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);
The obvious weakness here is cost. The resize event fires on every pixel of resizing, making any logic attached to it an expensive operation—even on an otherwise empty page the performance impact is measurable compared to matchMedia().


Beyond performance, the resize approach is also limited in scope. It only measures viewport dimensions; it has no way to express conditions for things like orientation or print media. A width-based check can mimic one narrow slice of what CSS media queries can represent, but it can't match anything else.
Use case: orientation detection
A handy example where matchMedia wins out over resize checks is detecting orientation—something commonly needed in HTML5 game development and best tested on a mobile device. A simple query for landscape lets you branch logic appropriately without wrestling with width and height comparisons.
For responsive JavaScript components such as sliders that need to recalculate item dimensions at certain resolutions, combining matchMedia() with addListener() provides the same sensitivity to context changes that CSS developers have always relied on, but with the ability to run JavaScript logic in response.



