For some time now, I’ve been using the enquire.js library to augment the use of media queries in JavaScript. I’ve had a lot of success using the library in various projects, but most developers I’ve met confessed they’ve never used or even heard of it. In this article, I want to introduce you the library, explain why and how you’d want to use it.
What is enquire.js?
enquire.js is a lightweight, pure JavaScript library for responding to CSS media queries.In my own words, enquire.js gives you additional functionality and flexibility on top of
window.matchMedia()
when working with media queries in JavaScript.
The library was written by Nick Williams and it’s been around for about three years, having a healthy amount of open source activity. Its aim is not to replace or polyfill matchMedia
; rather, it exists to provide additional functionality around media queries that don’t exist natively.
Why Would I Use It?
There are lots of use cases where enquire.js could be used, including:- Move nodes around the DOM
- Load supplementary content (e.g. ads) via Ajax
- Load and run a JavaScript library (e.g. Packery) to enhance a page
DOM Manipulation
Although there are some performance and maintainability considerations with using JavaScript to manipulate the DOM, there are many reasons why would do this. Let’s assume that on your blog, you have a bio with an image in a sidebar. On small screens, the sidebar is hidden – but you still want the bio visible at the end of your post. Instead of duplicating the bio (and image) markup, you could move it around the DOM depending on the screen size avoiding markup duplication. Here’s an example:window.$ = document.querySelector.bind(document);
enquire.register("screen and (max-width:40em)", {
match: function() {
$(".Post-content").appendChild($(".Bio"));
},
unmatch: function() {
$(".Sidebar").insertBefore($(".Bio"), $(".Sidebar").firstChild);
}
});
A live demo of this example is shown below:
See the Pen MwNYjp by SitePoint (@SitePoint) on CodePen.
This is a rudimentary example, and honestly doesn’t do much more than what nativematchMedia()
provides. In fact, here’s how you could do this with just matchMedia()
:
window.$ = document.querySelector.bind(document);
(function() {
var mq = window.matchMedia("(min-width:40em)");
mq.addListener(positionBio);
function positionBio(mediaQuery) {
if (mediaQuery.matches) {
$(".Sidebar").insertBefore($(".Bio"), $(".Sidebar").firstChild);
} else {
$(".Post-content").appendChild($(".Bio"));
}
}
// On load
positionBio(mq);
}());
A live demo of this example is shown below:
See the Pen WvVbor by SitePoint (@SitePoint) on CodePen.
Let’s get back to enquire.js and take the example from above a step further. In the next code we’ll use thesetup
function. It’s a function that runs just once as soon as enquire.register
is executed. In the example we’ll also cache a few selectors to improve the performance of the code, and make it more readable and maintainable. While this is a contrived example (and you could do the same without enquire.js), it enables me to introduce you to the setup
function and to explore more complex examples:
window.$ = document.querySelector.bind(document);
enquire.register("screen and (max-width:40em)", {
setup: function() {
this.bio = $(".Bio");
this.content = $(".Post-content");
this.sidebar = $(".Sidebar");
},
match: function() {
this.content.appendChild(this.bio);
},
unmatch: function() {
this.sidebar.insertBefore(this.bio, this.sidebar.firstChild);
}
});
A live demo of this example is shown below:
See the Pen MwNYbp by SitePoint (@SitePoint) on CodePen.
Supplementary Content
Let’s focus our attention on another use case: loading ad content via Ajax depending on the size of the viewport. This example uses thesetup()
function again and introduces another feature of enquire.js: deferSetup()
. It also uses the reqwest Ajax library (no typo here) and the classList
API to demonstrate how a more complex example could be written without jQuery. In case you don’t know what this API does, you can read the article Exploring the classList API.
In the next example, inside the setup
method (that I remind you that only runs once, when this media query matches), we use jQuery’s ajax()
method to request the page ad.html
and to store the result in an ad
property. Then, we set the content of .Ad
to the property and show the container by adding an is-visible
class (handled with CSS).
If the media query is ever “unmatched”, we’ll remove the is-visible
class that will, in turn, hide the .Ad
container.
Finally, we’ll use the deferSetup
flag along with the setup()
method so that the Ajax request only happens once, and only when the media query is matched. This is useful because the call to Ajax is delayed until the point the information is needed instead of making a premature request.
The code that implements what I’ve just described is reported below:
window.$ = document.querySelector.bind(document);
enquire.register("screen and (min-width:40em)", {
deferSetup: true,
setup: function() {
this.ad = "";
this.adContainer = $(".Ad");
this.visibleClass = "is-visible";
this.adUrl = "//codepen.io/damonbauer/pen/LVgxxN.html";
reqwest({ url: this.adUrl, crossOrigin: true})
.then(function(response) {
this.ad = response;
}.bind(this)).fail(function() {
this.ad = "Ad could not be loaded.";
}.bind(this)).always(function(response) {
this.adContainer.innerHTML = this.ad;
}.bind(this));
},
match: function() {
this.adContainer.classList.add(this.visibleClass);
},
unmatch: function() {
this.adContainer.classList.remove(this.visibleClass);
}
});
In addition to the previous JavaScript code, we also have to use the small CSS snippet reported below:
.Ad {
display: none;
}
.is-visible {
display: block;
}
A live demo of this example is shown below:
See the Pen vOoEyb by SitePoint (@SitePoint) on CodePen.
Page Enhancements
In this section, we’ll take a look at adding the Packery library to enhance a page at larger sizes. According to its documentation, Packery “fills empty gaps”. It helps you accomplish something similar to Pinterest’s layout, where cards fill available space in a grid. Let’s say that you have the following HTML in your page:<div id="Container">
<div class="Item">...</div>
<div class="Item">...</div>
<div class="Item">...</div>
...
</div>
The following code will use the packery library to achieve what I previously described:
enquire.register("screen and (min-width:30em)", {
deferSetup: true,
setup: function() {
this.container = $( "#Container" );
},
match: function() {
this.container.packery({
itemSelector: '.Item'
});
},
unmatch: function() {
this.container.packery('destroy');
}
});
A live demo of this example is shown below:
See the Pen OVKPWL by SitePoint (@SitePoint) on CodePen.
This is pretty similar to the first example. It starts by storing a container as a property in thesetup()
method. Then, if the media query matches, it’ll layout items following the packery
convention; otherwise we destroy the packery
instance by calling its destroy
method.
A potential use case for this example might be a tablet being rotated from landscape to portrait. Perhaps we’ve determined that the screen is too narrow to display the items in a certain way, so we can opt for the items to be stacked vertically.
Potential Pain Points
Hopefully, you’ve gotten a glimpse at how quick and powerful enquire.js can be to use. I’d like to share a couple of instances where I’ve run into problems when using the library.Old Versions of Internet Explorer
While it doesn’t fully support IE8, I can tell you that sites I built are don’t have any render-breaking JavaScript errors. Enquire.js depends on thematchMedia
API, which is not supported in versions of Internet Explorer prior to 10. In case you have to support such browsers, I suggest you to use the matchMedia polyfills written by Paul Irish.
To do so, you have to load the files provided before enquire.js. Moreover, I suggest you to place these scripts in an IE conditional comment as shown below:
<!--[if lte IE 9]>
<script src="/path/to/matchMedia.js"></script>
<script src="/path/to/matchMedia.addListener.js"></script>
<![endif]-->
Thanks to this approach, only the browsers who need the polyfills will load them. It’s important to highlight that even if you load them in browsers supporting these features, you’ll still have the native implementation as both the scripts are written in a non-invasive way. This means that before executing any code, they detect if the browser supports the features natively. If that’s the case, the polyfill code is skipped altogether.
Manipulating the DOM
In one of the examples above, I showed how to use enquire.js to manipulate the DOM. While this technique works, I would advise a healthy bit of caution in employing it. Watch out for adding lots of DOM changes in multiple enquire.jsmatch
and unmatch
methods as the more operations you add, the harder it’ll become to debug the page if something goes wrong. In addition, since manipulating the DOM is usually slow, using this technique can lead to page jank and poor performance.
Progressive Content
My suggestion is to use enquire.js to “progressively” provide content or functionality, instead of rely on it to show critical parts of content. My advice is to initially show basic content and then enhance it with enquire.js, rather than depending on all your content being enhanced. In case of the page enhancements’ example, the grid of items is visible by default; if the screen is large enough, the items are laid out using the Packery.js library. This ensures that if for whatever reason (e.g. broken JavaScript, slow connection, and so on) the JavaScript isn’t executed, a user can still consume the content.Mobile First
It’s a common and suggested practice these days to build sites using a mobile-first approach. If a browser you need to support doesn’t understand media queries (such as IE8), enquire.js has a parameter calledshouldDegrade
that comes in handy. It specifies that the result of the enquire.register
block should always be executed if the browser doesn’t understand media queries. By default, it’s value is set to false
but you can change it to true
to fit your needs.
An example of use of this parameter is reported below:
enquire.register("screen and (min-width:40em)", function() {
// execute some code for large-screen devices
}, true); // note the true!
By using snippets like this, you can still build mobile-first websites and support older browsers to have a desktop experience. My advise is to use this parameter or the polyfills mentioned above, not both.
Conclusions
In this article I’ve introduced you to enquire.js, a powerful library written in pure JavaScript for responding to CSS media queries. Hopefully, I’ve demonstrated you how it gives you extra features on top of the nativematchMedia()
method to allow you to build performant, feature-rich websites across all screen sizes. While this has not been an exhaustive overview of the library, this should be enough to push you to learn more about it and to think if there’s a place for it in your projects.
Have you ever heard about enquire.js? Have you ever tried to use it in your projects? What about your results? Share your comments below and let’s start a discussion!
Frequently Asked Questions about Enquire.js
What is Enquire.js and what is it used for?
Enquire.js is a lightweight, pure JavaScript library for handling media queries. It is a powerful tool for web developers, allowing them to programmatically respond to changes in a website’s environment, such as screen size or device orientation. This makes it easier to create responsive designs that adapt to different devices and screen sizes. It’s particularly useful for handling complex responsive design scenarios where CSS media queries may not be sufficient.
How do I install and use Enquire.js in my project?
To install Enquire.js, you can use npm by running the command npm install enquire.js
. Once installed, you can import it into your JavaScript file using import enquire from 'enquire.js'
. You can then use the enquire.register
method to register a media query and provide a callback function to be executed when the media query is matched.
Can I use Enquire.js with other JavaScript libraries or frameworks?
Yes, Enquire.js can be used alongside other JavaScript libraries or frameworks. It does not have any dependencies and does not interfere with other libraries or frameworks. This makes it a versatile tool that can be integrated into a wide range of projects.
How does Enquire.js handle changes in device orientation?
Enquire.js responds to changes in device orientation by re-evaluating all registered media queries. This means that if a media query that was previously matched no longer matches after a change in orientation, the appropriate callback function will be triggered.
What browsers are supported by Enquire.js?
Enquire.js supports all modern browsers, including Chrome, Firefox, Safari, and Edge. It also supports Internet Explorer 9 and above. However, for older browsers that do not support media queries, such as Internet Explorer 8, a polyfill will be required.
How can I unregister a media query in Enquire.js?
To unregister a media query in Enquire.js, you can use the enquire.unregister
method. This method takes the same media query string that was used to register the media query and removes it from Enquire.js’s internal registry.
Can I use Enquire.js to test for features other than screen size?
While Enquire.js is primarily designed to handle media queries related to screen size and device orientation, it can also be used to test for other features that can be detected through media queries. This includes features like color depth, resolution, and aspect ratio.
How does Enquire.js handle errors?
Enquire.js provides a fail
method that can be used to specify a callback function to be executed in case of an error. This allows you to handle errors gracefully and provide a fallback in case a media query cannot be evaluated.
Can I use Enquire.js in a server-side environment?
Enquire.js is designed to be used in a client-side environment and relies on the window
object to access media queries. Therefore, it cannot be used in a server-side environment like Node.js without a virtual DOM implementation.
Is Enquire.js still maintained and updated?
As of the time of writing, Enquire.js is not actively maintained. The last update was in 2018. However, it is a stable library and continues to be widely used due to its simplicity and effectiveness.
![Damon Bauer](https://uploads.sitepoint.com/wp-content/uploads/2015/08/1440453968damonbauer-96x96.jpg)
Damon is a Front End Developer from Nashville, TN. He is a husband, father, coffee enthusiast, pretend woodworker and mountain bike poseur.