Using media queries with JavaScript
Tags: javascript, webdev, css, tutorial
Published: 2021-03-30 19:18:54

Media queries are not limited to CSS. JavaScript can also react to them. This can be very useful when building applications.

---

> If you're looking for an existing solution for using media queries in JavaScript, checkout my small library [mediaq](https://dev.maroun-baydoun.com/mediaq/).

---

# The window.matchMedia API

Browsers expose the [window.matchMedia]("https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia") method. It takes a media query as an argument and returns a `MediaQueryList` object.

``` js
 const mediaQueryList = window.matchMedia("only screen and (max-width: 600px");
```

# Checking if a media query matches

Once created, a `MediaQueryList` object has the boolean property `matches`. Use that property to check, at any time, if the media query is matching. 


``` js
 if (mediaQueryList.matches) {
    console.log("It matches!");
 } else {
    console.log("It doesn't match.");
 }
```

# Listening for updates

Instead of checking if the `MediaQueryList` object matches, you can attach an event listener to it. The listener will trigger whenever the media query matches or stops matching (the window is resized, the device orientation changes etc.).

Since `MediaQueryList` inherits `EventTarget`, listening to the events it fires is very straightforward.

``` js
const listener = (event) => {
    console.log(event.matches ? "It matches!" : "It doesn't match.");
};

mediaQueryList.addEventListener("change", listener);
```

Removing a listener is also as easy

``` js
mediaQueryList.removeEventListener("change", listener);
```


Internet explorer and Safari < 14 handle those event listeners  differently. They use `addListener`/`removeListener` instead.

To support those browsers as well, you can conditionally call the correct method.

``` js
const listener = (event) => {
    console.log(event.matches ? "It matches!" : "It doesn't match.");
};

if (mediaQueryList.addEventListener) {
  mediaQueryList.addEventListener("change", listener);
} else {
  mediaQueryList.addListener(listener);
}


// For removal

if (mediaQueryList.removeEventListener) {
  mediaQueryList.removeEventListener("change", listener);
} else {
  mediaQueryList.removeListener(listener);
}

```

You can read more about [browser compatibility](https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList#browser_compatibility).


# Why use media queries with JavaScript?

When applied through CSS, media queries help create responsive layouts. They also allow hiding certain elements on the web page and loading higher/lower resolution background pictures. 

In some scenarios that is not enough. That's when JavaScript can be used to optimize the webpage further. 

Imagine a component of your webpage is computationally heavy and you decide you don't need it to display on smaller screens. In CSS, you can easily hide it, but it would still exist as part of your DOM and could still weigh down the performance of your web application.

``` css
@media only screen and (max-width: 480px") {
 .component {
   display: none; /* The component is hidden but is still part of the webpage.*/
 }
}
```

In JavaScript, on the other hand, you could decide whether or not to append the element to the document.

``` js
const mediaQueryList = window.matchMedia("only screen and (max-width: 480px");

if (!mediaQueryList.matches) {
 // Create/Append the element here
}

```

Another use case is loading certain scripts for certain screen sizes. If you application uses large graphing libraries, you can choose to include them only on desktop-size devices, where the graphs are being displayed. 

``` js
const mediaQueryList = window.matchMedia("only screen and (min-width: 768px");

if (mediaQueryList.matches) {
  const script = document.createElement("script");
  script.src = "path to JavaScript script";
  document.body.appendChild(script);
}

```


JavaScript can detect [screen resolution](https://developer.mozilla.org/en-US/docs/Web/API/Screen) without using media queries. This can work for one-time checks. Listening to updates with the `resize` event on the window object can be expensive. Using media queries is much more efficient.