DEV Community

loading...
Cover image for Media queries in JS

Media queries in JS

dannyviiprus profile image Dannyvpz ・3 min read

Original article - written by Marko Ilic

Media query is a CSS technique introduced in CSS3.

CSS media queries are a core ingredient in any responsive design. They’re a great way to apply different styles to different contexts.

The old way to detect media queries in JS is using window innerWidth as sample code below:

function checkMediaQuery() {
  // If the inner width of the window is greater then 768px
  if (window.innerWidth > 768) {
    doResponsiveThings();
  }
}

window.addEventListener('resize', checkMediaQuery);
Enter fullscreen mode Exit fullscreen mode

Using matchMedia()

To determine if the document matches the media query string in JavaScript, we use the matchMedia() method. Even though it’s officially part of the CSS Object Model View Module specification which is in Working Draft status, the browser support for it is great going as far back as Internet Explorer 10 with 98.6% global coverage.

Caniuseit

Caniuseit

The usage is nearly identical to CSS media queries. We pass the media query string to matchMedia() and then check the .matches property.

const mediaQuery = window.matchMedia('(min-width: 768px)')
Enter fullscreen mode Exit fullscreen mode

The defined media query will return a MediaQueryList object. It is an object that stores information about the media query and the key property we need.

const mediaQuery = window.matchMedia('(min-width: 768px)')
// Check if the media query is matched
if (mediaQuery.matches) {
  doResponsiveThings();
}
Enter fullscreen mode Exit fullscreen mode

That’s the basic usage for matching media conditions in JavaScript. But there’s more to it. For example, if we were change the window size below our target window size, nothing updates the way it will with CSS right out of the box.

Listen for changes

MediaQueryList has an addListener() (and the subsequent removeListener()) method that accepts a callback function that’s invoked when the media query status changes. we can fire additional functions when the conditions change, allowing us to “respond” to the updated conditions.

const mediaQuery = window.matchMedia('(min-width: 768px)')

function handleTabletChange(e) {
  // Check if the media query is true
  if (e.matches) {
    doResponsiveThings();
  }
}

// Register event listener
mediaQuery.addListener(handleWindowChange)

// Initial check
handleWindowChange(mediaQuery)
Enter fullscreen mode Exit fullscreen mode

We explored how matchMedia() allows us to define media conditions and examined the MediaQueryList object. We also saw the “old” way of doing things by listening for resize events on the window. While it’s still widely used and a totally legit way to respond to changes to the size of the window.innerWidth, it’s unable to perform checks on advanced media conditions.

Looking at the performance impact comparing with the old way:

image

More about @media queries - A Complete Guide to CSS Media Queries - by Andrés Galante

== Update from @rvxlab comment

MediaQueryList.addListener is marked as deprecated, MediaQueryList extends from EventTarget so you can use addEventListener instead. Except for Safari 13 & earlier we can do fallback condition as below:


// Register event listener
if (mediaQuery.addEventListener) {
  mediaQuery.addEventListener('change', handleWindowChange);
} else {
  mediaQuery.addListener(handleWindowChange);
}
Enter fullscreen mode Exit fullscreen mode

Discussion (2)

pic
Editor guide
Collapse
rvxlab profile image
RVxLab • Edited
// Register event listener
mediaQuery.addListener(handleWindowChange)
Enter fullscreen mode Exit fullscreen mode

Mind you that MediaQueryList.addListener is deprecated, MediaQueryList extends from EventTarget so you can use addEventListener instead.

Notable exception being Safari 13 and earlier, which doesn't do this.

The ideal solution is to check for addEventListener and fall back to addListener when it's not available:

const mediaQuery = window.matchMedia('(min-width: 768px)')

function handleTabletChange(e) {
  // Check if the media query is true
  if (e.matches) {
    doResponsiveThings();
  }
}

// Register event listener
if (mediaQuery.addEventListener) {
  mediaQuery.addEventListener('change', handleWindowChange);
} else {
  mediaQuery.addListener(handleWindowChange);
}

// Initial check
handleWindowChange(mediaQuery);
Enter fullscreen mode Exit fullscreen mode
Collapse
dannyviiprus profile image
Dannyvpz Author

Thanks for the update solution!