3

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).

nunop
  • 2,036
  • 2
  • 20
  • 36
  • The first fiddle you posted is working for me. What is the problem for you? It switches when that pane of JSFiddle is 400px wide. Actually both of them are working for me – Jeff Mar 31 '16 at 16:48
  • @Jeff the problem is that it is not matchin/unmatching the document size on page load. Meaning that in the JsFiddles above, it matches or umatches the pane size only when we manually resize it. – nunop Mar 31 '16 at 18:04
  • 1
    The `unmatch` only happens if you go from `match` to `unmatch`, it doesn't happen if you start in `unmatch` You should probably approach this mobile first and set `isSmallScreen` to `true` then change you query to `min-width` then switch them. – Bill Criswell Mar 31 '16 at 21:03

2 Answers2

3

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.

Bill Criswell
  • 32,161
  • 7
  • 75
  • 66
  • Thanks for the answer! I was hoping that this was it, but when I turn `Chrome device mode` on, it doesn't produce the intended result. On page load, or when I resize the browser's window manually, it works as intended. See [here for when it is large](https://gyazo.com/46ed7c337ec9aaaa3187de3bc45a44ef) and [here for when it is small](https://gyazo.com/3bd972a445c583926bf049372ee34cba). However, when I turn `Chrome device mode` [on, with a 320px-wide device](https://gyazo.com/fd8655d759cd95b9eaacfee54ed45b33), it doesn't toggle to small as it should. – nunop Mar 31 '16 at 21:54
  • The screen shots aren't super helpful without code. Just to be clear though, nothing inside `unmatch` will happen unless `match` happens first. So you can resize that all you want under 400px and that `unmatch` will never fire unless you go from over 400px to under it again. – Bill Criswell Mar 31 '16 at 22:17
  • Thank you for the clarification. Still, don't get it why this code is turning a `match` when the browser loads (as well as on resize), if the browser's window is less than 400px wide, while the same thing doesn't happen when Chrome's `toggle device mode` is on (or when accessing the page from a mobile phone). – nunop Mar 31 '16 at 22:38
  • I totally forgot about some css properties that needed to be changed accordingly... I will accept your answer given that I now get a `match` when the page loads, whereas before I had to resize the window before anything happened. Thanks again! – nunop Mar 31 '16 at 22:56
  • 1
    This should hopefully clear it the situation a bit: https://jsfiddle.net/crswll/uc7gaec0/1/ – Bill Criswell Apr 01 '16 at 01:15
  • Hi, thanks for the new JsFiddle! I think it's lacking some html though ;-) – nunop Apr 01 '16 at 09:53
  • It just needs console.log(). Shows how, when things are called. – Bill Criswell Apr 01 '16 at 13:26
0

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.

nunop
  • 2,036
  • 2
  • 20
  • 36