Enquire.js does not match initially, only on resize

685 views Asked by At

I'm doing media queries with Enquire.js and Vue.js. It all pretty much works when I resize the browser's window manually. However, I get no match on document load, an odd behavior that is most obvious when switching Chrome's toggle device mode on or when accessing the site on a mobile phone. I checked with the "Match & Unmatch Example", and it works as expected in said mode or when accessing it with a mobile phone. I wonder if there's some sort of incompatibility between Vue.js and Enquire.js or am I doing something wrong?

The logic for the media queries is on my vue instance's ready hook:

ready:
    function () {
        var self = this;
        enquire.register("screen and (max-width: 400px)", {
            match: function () {
                self.displayIsLarge = false;
                self.displayIsSmall = true;
            },
            unmatch: function () {
                self.displayIsLarge = true;
                self.displayIsSmall = false;
            }
        })
    );

On my vue instance, I've the following data properties:

var menu = new Vue({
el: '#app',
data: {
    displayIsLarge: true,
    displayIsSmall: false,

On my html file, I'm using v-if="displayIsSmall" and v-if="displayIsLarge" to hide/display elements according to the browser's size. JsdFiddle here.

It came to my mind in the meanwhile, that I might be able to solve this issue with the Setup callback, perhaps with a conditional, something like this:

enquire.register("screen and (max-width: 400px)", {
    setup: function() {
        if (this.match) {
            self.displayIsSmall = true;
        }
        else {
            self.displayIsSmall = false;
        }
    },
    match: function () {
        self.displayIsLarge = false;
        self.displayIsSmall = true;
    },
    unmatch: function () {
        self.displayIsLarge = true;
        self.displayIsSmall = false;
    }
})

This is not working as expected. What am I missing? JsdFiddle here.


UPDATE

No luck either with Vue's beforeCompile or created hooks (instead of ready).

2

There are 2 answers

7
Bill Criswell On BEST ANSWER

The unmatch only happens if you go from match to unmatch. Therefore it won't happen till you go under 400px then back over it. I recommend you take a mobile first approach and do something like this instead.

new Vue({
  el: '#app',
  data: {
    displayIsLarge: false,
    displayIsSmall: true
  },
  ready: function () {
    var self = this;
    enquire.register("screen and (min-width: 400px)", {
        match: function () {
            self.displayIsLarge = true;
            self.displayIsSmall = false;
        },
        unmatch: function () {
            self.displayIsLarge = false;
            self.displayIsSmall = true;
        }
    })
  }
})

Here's a small demo: https://jsfiddle.net/crswll/uc7gaec0/

Though, depending on what these elements are actually containing and/or doing it probably makes more sense to just toggle them visually with CSS. You know what's going on better than me, though.

0
nunop On

In addition to making sure I got a match on page load and not only after a resize (as detailed in the above answer), I had to add a <meta> viewport tag in my index.html. Adding the following metatag for instance will force the viewport to scale to the device's dimensions, now rendering the correct style (i.e., mobile):

<meta name="viewport" content="width=device-width, initial-scale=1">

The width=device-width will make an equivalence between the width of page to that of the device, whereas initial-scale=1 will set the initial zoom when the pages loads.

More details here.