211

I am trying to write a JavaScript function to get the current browser width.

I found this one:

console.log(document.body.offsetWidth);

But its problem that it fail if the body has width 100%.

Is there any other better function or a workaround?

LWC
  • 1,084
  • 1
  • 10
  • 28
Amr Elgarhy
  • 66,568
  • 69
  • 184
  • 301

9 Answers9

309

It's a pain in the ass. I recommend skipping the nonsense and using jQuery, which lets you just do $(window).width().

chaos
  • 122,029
  • 33
  • 303
  • 309
  • 2
    If I recalled correctly, jQuery has pulled much of dimensions into the core. Do you still need dimensions to do what you're suggesting? – Nosredna Jun 24 '09 at 14:41
  • Turns out you don't. Which is awesome. Edited answer per. Thanks for the heads-up. – chaos Jun 24 '09 at 14:43
  • 6
    The $(window).width() support in jQuery is since version 1.2, in case it's relevant to anybody. – chaos Jun 24 '09 at 14:44
  • 20
    I've found that $(window).width() does not always return the same value as innerWidth / clientWidth as per the examples in the answer below. jQuery's version doesn't take browser scrollbars into account (in FF anyway). This caused me a lot of confusion with CSS @media queries appearing to trigger at the wrong width. Using native code seems to be more reliable as it takes the appearance of the scrollbars into account. – Coder Jan 19 '13 at 10:17
  • 13
    Adding 30k lines of code to get window width is a BAD solution! – codechimp Feb 07 '18 at 16:34
  • 2
    @codechimp "Adding 30k lines of code to get window width is a BAD solution!" Proceeds to add a 80k file just to get window width. Bad is relative. – Madness Feb 08 '18 at 21:45
  • Use jQuery in a react app? nah bro – Adam Fowler Mar 08 '21 at 20:40
192

Update for 2017

My original answer was written in 2009. While it still works, I'd like to update it for 2017. Browsers can still behave differently. I trust the jQuery team to do a great job at maintaining cross-browser consistency. However, it's not necessary to include the entire library. In the jQuery source, the relevant portion is found on line 37 of dimensions.js. Here it is extracted and modified to work standalone:

function getWidth() {
  return Math.max(
    document.body.scrollWidth,
    document.documentElement.scrollWidth,
    document.body.offsetWidth,
    document.documentElement.offsetWidth,
    document.documentElement.clientWidth
  );
}

function getHeight() {
  return Math.max(
    document.body.scrollHeight,
    document.documentElement.scrollHeight,
    document.body.offsetHeight,
    document.documentElement.offsetHeight,
    document.documentElement.clientHeight
  );
}

console.log('Width:  ' +  getWidth() );
console.log('Height: ' + getHeight() );

Original Answer

Since all browsers behave differently, you'll need to test for values first, and then use the correct one. Here's a function that does this for you:

function getWidth() {
  if (self.innerWidth) {
    return self.innerWidth;
  }

  if (document.documentElement && document.documentElement.clientWidth) {
    return document.documentElement.clientWidth;
  }

  if (document.body) {
    return document.body.clientWidth;
  }
}

and similarly for height:

function getHeight() {
  if (self.innerHeight) {
    return self.innerHeight;
  }

  if (document.documentElement && document.documentElement.clientHeight) {
    return document.documentElement.clientHeight;
  }

  if (document.body) {
    return document.body.clientHeight;
  }
}

Call both of these in your scripts using getWidth() or getHeight(). If none of the browser's native properties are defined, it will return undefined.

Travis
  • 12,001
  • 8
  • 39
  • 52
  • 16
    Best answer because I dont have to include a 33k library for a simple redirect based on browser window width – David Aguirre Jun 21 '14 at 17:21
  • 1
    This produces the right (or expected) results consistently compared to jQuery's implementation. – Emmanuel John Aug 17 '14 at 05:04
  • 3
    ... each of these three shows some result and all results (widths) are different. For example with Google Chrome see `self.innerWidth 423`, `document.documentElement.clientWidth 326` and `document.body.clientWidth 406`. In such case question: which is correct and which to use? For example i want to resize google map. 326 or 423 big difference. If width ~ 700, then see 759, 735, 742 (not so big difference) – Andris Mar 13 '15 at 04:00
  • 1
    @user2118559 `var pageWidth = Math.max(self.innerWidth || 0, document.documentElement.clientWidth || 0, document.body.clientWidth || 0);` and `var windowWidth = self.innerWidth || -1;` // because of "body" or "screen" or "document" are not the "window" if you check an overflowed content of html you can understand. # http://i.stack.imgur.com/6xPdH.png – Abdullah Apr 03 '16 at 11:32
  • 1
    @Travis is this still true in 2017? Or is `window.innerWidth` enough today? – pyronaur Jul 25 '17 at 16:49
  • 1
    @Norris I've updated my answer. I looked at the jQuery source to see how they do it now (in 2017). While window.innerWidth will probably work in most cases, I trust the jQuery team and their ability to maintain cross-browser consistency. For that reason, I use their code, only modified to run without the full jQuery library. – Travis Jul 31 '17 at 20:43
  • Warning! If you are trying to use it to detect browser's portrait/landscape mode or the screen's aspect ratio, the heigh values will return the very long, multi-page height. For example on this very page: 7305. The only value you should use is window.outerHeight/Width! – hyperknot Jan 16 '20 at 02:14
65
var w = window.innerWidth;
var h = window.innerHeight;
var ow = window.outerWidth; //including toolbars and status bar etc.
var oh = window.outerHeight;

Both return integers and don't require jQuery. Cross-browser compatible.

I often find jQuery returns invalid values for width() and height()

Bradley Flood
  • 10,233
  • 3
  • 46
  • 43
28

Why nobody mentions matchMedia?

if (window.matchMedia("(min-width: 400px)").matches) {
  /* the viewport is at least 400 pixels wide */
} else {
  /* the viewport is less than 400 pixels wide */
}

Did not test that much, but tested with android default and android chrome browsers, desktop chrome, so far it looks like it works well.

Of course it does not return number value, but returns boolean - if matches or not, so might not exactly fit the question but that's what we want anyway and probably the author of question wants.

Dariux
  • 3,953
  • 9
  • 43
  • 69
10

From W3schools and its cross browser back to the dark ages of IE!

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

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

var h = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;

var x = document.getElementById("demo");
x.innerHTML = "Browser inner window width: " + w + ", height: " + h + ".";

alert("Browser inner window width: " + w + ", height: " + h + ".");

</script>

</body>
</html>
user3651121
  • 101
  • 1
  • 3
7

Here is a shorter version of the function presented above:

function getWidth() {
    if (self.innerWidth) {
       return self.innerWidth;
    }
    else if (document.documentElement && document.documentElement.clientHeight){
        return document.documentElement.clientWidth;
    }
    else if (document.body) {
        return document.body.clientWidth;
    }
    return 0;
}
Community
  • 1
  • 1
ismael
  • 71
  • 1
  • 1
1

An important addition to Travis' answer; you need to put the getWidth() up in your document body to make sure that the scrollbar width is counted, else scrollbar width of the browser subtracted from getWidth(). What i did ;

<body>
<script>
function getWidth(){
return Math.max(document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth);
}
var aWidth=getWidth();
</script>
</body>

and call aWidth variable anywhere afterwards.

burkul
  • 113
  • 1
  • 5
0

An adapted solution to modern JS of Travis' answer:

const getPageWidth = () => {
  const bodyMax = document.body
    ? Math.max(document.body.scrollWidth, document.body.offsetWidth)
    : 0;

  const docElementMax = document.documentElement
    ? Math.max(
        document.documentElement.scrollWidth,
        document.documentElement.offsetWidth,
        document.documentElement.clientWidth
      )
    : 0;

  return Math.max(bodyMax, docElementMax);
};
Sergiu
  • 1,397
  • 1
  • 18
  • 33
-1

function getWidth() {
  return Math.max(
    document.body.scrollWidth,
    document.documentElement.scrollWidth,
    document.body.offsetWidth,
    document.documentElement.offsetWidth,
    document.documentElement.clientWidth
  );
}

function getHeight() {
  return Math.max(
    document.body.scrollHeight,
    document.documentElement.scrollHeight,
    document.body.offsetHeight,
    document.documentElement.offsetHeight,
    document.documentElement.clientHeight
  );
}

console.log('Width:  ' +  getWidth() );
console.log('Height: ' + getHeight() );
Narendra
  • 4,514
  • 2
  • 21
  • 38
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 26 '21 at 19:16
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 27 '21 at 01:50