CSS media queries and JavaScript window width do not match

For a responsive template, I have a media query in my CSS:

@media screen and (max-width: 960px) {
 body{
 /*  something */
 background:red;
 }
}

And, I made a jQuery function on resize to log width:

$(window).resize(function() {
 console.log($(window).width());
 console.log($(document).width()); /* same result */
 /* something for my js navigation */
}

And there a difference with CSS detection and JS result, I have this meta:

<meta content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width" name="viewport"/> 

I suppose it's due to the scrollbar (15 px). How can I do this better?


Solution 1:

You're correct about the scroll bar, it's because the CSS is using the device width, but the JS is using the document width.

What you need to do is measure the viewport width in your JS code instead of using the jQuery width function.

This code is from http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/

function viewport() {
    var e = window, a = 'inner';
    if (!('innerWidth' in window )) {
        a = 'client';
        e = document.documentElement || document.body;
    }
    return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}

Solution 2:

I found following code on http://www.w3schools.com/js/js_window.asp:

var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;

Practically its working the same way as the answer in @Michael Bird's answer, but it's more easy to read.

Edit: I was looking for a method to give exactly the same width as it is used for css media queries. But the suggested one does not work perfect on Safari with scrollbars, sorry. I ended up using modernizr.js in one central function and in the rest of the code I just check if display type is mobile, tablet or desktop. As I am not interested in the width, this works fine for me:

getDisplayType = function () {
  if (Modernizr.mq('(min-width: 768px)')){
    return 'desktop';
  }
  else if (Modernizr.mq('(min-width: 480px)')){
    return 'tablet'
  }
  return 'mobile';
};

Solution 3:

window.innerWidth is what you need.

if (window.innerWidth < 768) works for 768 break point in CSS