Skip to main content

Bug Tracker

Side navigation

#14989 closed bug (migrated)

Opened April 11, 2014 10:05AM UTC

Closed October 20, 2014 11:25PM UTC

$(window).width() AND $(window).outerWidth() excluding the scrollbar width

Reported by: antti@mainiotech.fi Owned by: dmethvin
Priority: low Milestone: 1.12/2.2
Component: dimensions Version: 2.1.0
Keywords: Cc:
Blocked by: Blocking:
Description

It is sometimes annoying that $(window).width() or $(window).outerWidth() do not include the scrollbar width in their value. Especially when trying to match the window width to the CSS media queries.

Currently e.g. if you have a media query in the CSS such as

@media screen and (max-width: 1600px) {
  body {background: red;}
}

When the red background is actually applied to the document by the browser, jQuery tells the window width is less than 1600px (1600 - scrollbar width).

This is annoying e.g. in cases where there are some mobile-specific stuff that needs to be done in both, CSS and JS. And they would need to be done at the exactly same width of the document/window.

However, plain JavaScript returns 1600 as the window width when asked at the point of the breakpoint as follows:

console.log(window.innerWidth);

Is it possible to get either $(window).width() or $(windor).outerWidth() working consistently with the browser's actual width? $(document).width() and $('body').width() will not return the same as "window.innerWidth" either, they return the same as $(window).width() and $(window).outerWidth().

Fixing this would greatly help making consistent code with the CSS media queries.

Possible workarounds currently are:

  • Using plain javascript, i.e. window.innerWidth
  • Checking $('...').is(':visible') for some element that is visible only in the target width

Here's an example of what I mean:

http://jsfiddle.net/aq5vb/

Attachments (0)
Change History (18)

Changed April 11, 2014 10:06AM UTC by antti@mainiotech.fi comment:1

And this applies to earlier versions of jQuery as well, I just reported it for the latest stable.

Changed April 17, 2014 10:04PM UTC by dmethvin comment:2

I'm very concerned about changing this, considering the compatibility implications; it's been this way forever. For $(window).width() we return document.documentElement.clientWidth which does not include the scrollbars as you've observed. We say that is "the width of the viewport".

http://api.jquery.com/width/

Any other opinions on this? If people expect it to exclude scrollbars we would break a lot of code by changing it.

Changed April 17, 2014 10:20PM UTC by anonymous comment:3

I'm not sure if I articulated myself very clearly but what I actually meant was that the jQuery width in fact EXCLUDES the scroll bar from the width while the CSS media queries count it as part of the viewport.

Here's an image that might (or not) emphasize my point (see also the CSS that defines the breakpoint):

[[Image(http://i.imgur.com/2mtrjGw.jpg)]]

If you say it's the "width of the viewport", shouldn't it be consistent with what the browser considers as the viewport width then?

I understand that it would might things but it just bothers me that it does not match the width that the CSS media queries are using, i.e. the width of the viewport. In fact, none of these do (you can test this by changing it in the jsFiddle above):

$(window).width();
$(window).innerWidth();
$(window).outerWidth();

Any possibility to get even ONE of these working consistently with the browser's viewport width?

Changed April 18, 2014 12:10AM UTC by dmethvin comment:4

Yes, you made yourself clear. My point was that as far as I can tell we have been doing it this way for a long time. If we change it there is a very good chance that we will break someone's code who expects the width to include only the client area. Still looking for feedback from others.

Changed April 18, 2014 12:15AM UTC by scottgonzalez comment:5

Please don't change this. Honestly, it's strange that the media queries include the scrollbars since developers are obviously using things like (max-width: 600px) based on actual usable space, and that excludes scrollbars.

I'd expect tons of broken sites if jQuery changed, but almost no broken sites if media queries changed. Just a thought...

Changed April 18, 2014 07:38AM UTC by antti@mainiotech.fi comment:6

I understand that changing $(window).width() would break things.

I don't think changing $(window).outerWidth() would break anything.

Changed April 18, 2014 07:44AM UTC by antti@mainiotech.fi comment:7

And could someone also post me an example of a code that would break or behave strangely if this was changed? I'm not quite sure if I currently even see the risk as high as you guys.

Changed April 18, 2014 10:03AM UTC by antti@mainiotech.fi comment:8

And just adding to this, looking closer to the API documentation of .width().

It states the following:

// Returns width of browser viewport
$( window ).width();
 
// Returns width of HTML document
$( document ).width();

So, if $(window).width() currently returns document.documentElement.clientWidth, isn't this wrong regarding to the API documentation?

Changed April 18, 2014 12:13PM UTC by scottgonzalez comment:9

And could someone also post me an example of a code that would break or behave strangely if this was changed?

Anything that positions elements relative to the window, e.g., notifications. Positioning against the top right corner would overflow and cause a horizontal scrollbar.

Anything that sizes elements relative to the window, e.g., overlays. The overlay would be too large and would cause a horizontal scrollbar.

Anything that does bounds testing against the window, e.g., draggable elements contained to the window. The bounds would be slightly too wide and would cause a horizontal scrollbar at the right edge, increasing the size of the document and the bounds.

There are likely several other scenarios as well. Those are the generic cases that popped into my head right away.

Changed April 18, 2014 01:00PM UTC by antti@mainiotech.fi comment:10

Does not sound something I would do with jQuery, I think all of these cases are handled by CSS in most occasions. But the bounds part, you're correct on that one.

But yeah, it might break such things because of which I was looking for actual references to existing code that I could test against (e.g. links to github projects).

Changed April 28, 2014 02:17PM UTC by dmethvin comment:11

component: unfileddimensions
milestone: None1.12/2.2
priority: undecidedlow
status: newopen

It seems highly unlikely that anyone would be using $(window).outerWidth() today so I'll mark this open for now and a potential change for 1.12/2.2.

Changed May 05, 2014 04:08PM UTC by dmethvin comment:12

owner: → dmethvin
status: openassigned

Changed May 05, 2014 04:11PM UTC by scottgonzalez comment:13

Replying to [comment:11 dmethvin]:

It seems highly unlikely that anyone would be using $(window).outerWidth() today so I'll mark this open for now and a potential change for 1.12/2.2.

#9434

Changed May 05, 2014 05:36PM UTC by dmethvin comment:14

Why do we have all 3 return the same value? I'm wondering about the use case that spawned #9434.

Changed May 05, 2014 05:45PM UTC by scottgonzalez comment:15

The use case is generic plugins that operate on elements, documents, and windows. For example, a plugin that centers x inside y would do something like:

x.css( "left", (y.outerWidth() - x.outerWidth()) / 2 );

The correct behavior would be achieved today even if y is a window. However, if the scrollbar width is included, x would be off-center by half the size of the scrollbar. To compensate for this, you would need to check for windows:

var yWidth = $.isWindow( y[ 0 ] ) ? y.width() : y.outerWidth();
x.css( "left", (yWidth - x.outerWidth()) / 2 );

Note that this extended logic is already required if you want to support jQuery <1.7 since that didn't support .outerWidth() on windows.

Changed May 05, 2014 05:48PM UTC by scottgonzalez comment:16

Changed July 29, 2014 03:22PM UTC by emartel comment:17

Hi,

Sorry I don't have a strong web development background but I'm very interested in the topic and I thought one of the best way to learn more is to collaborate with existing projects.

I've given some thoughts about this problem, and I'm wondering if there wouldn't be a simple solution to it...

I'm not sure how "elegant" this solution is, but it might be a start to handle legacy code and new code that wants an outerWidth that takes scrollbars into account.

Would it be an option to add a "state" to the window jQuery object? By default, the state is legacy / no-scrollbar / a decent name that explains the behavior of calls made on this object. Using a function call such as $(window).sizeExcludesScrollbars(true/false), the state is altered and the state is persisted, making subsequent calls to width / height take scollbars into account or not?

I believe that such a change would give Antti what he wants while leaving existing code described by Scott functional.

What do you guys think?

Changed October 20, 2014 11:25PM UTC by m_gol comment:18

resolution: → migrated
status: assignedclosed