I've run into an odd issue with what appears to be various versions of Webkit browsers. I'm trying to position an element on the center of the screen and to do the calculations, I need to get various dimensions, specifically the height of the body and the height of the screen. In jQuery I've been using:
var bodyHeight = $('body').height();
var screenHeight = $(window).height();
My page is typically much taller than the actual viewport, so when I 'alert' those variables, bodyHeight should end up being large, while screenHeight should remain constant (height of the browser viewport).
This is true in
- Firefox
- Chrome 15 (whoa! When did Chrome get to version 15?)
- Safari on iOS5
This is NOT working in:
- Safari on iOS4
- Safari 5.0.4
On the latter two, $(window).height(); always returns the same value as $('body').height()
Thinking it was perhaps a jQuery issue, I swapped out the window height for window.outerHeight but that, too, does the same thing, making me think this is actually some sort of webkit problem.
Has anyone ran into this and know of a way around this issue?
To complicate things, I can't seem to replicate this in isolation. For instance: http://jsbin.com/omogap/3 works fine.
I've determined it's not a CSS issue, so perhaps there's other JS wreaking havoc on this particular browser I need to find.
I've been fighting with this for a very long time (because of bug of my plugin) and I've found the way how to get proper height of window in Mobile Safari.
It works correctly no matter what zoom level is without subtracting height of screen with predefined height of status bars (which might change in future). And it works with iOS6 fullscreen mode.
Some tests (on iPhone with screen size 320x480, in landscape mode):
// Returns height of the screen including all toolbars
// Requires detection of orientation. (320px for our test)
window.orientation === 0 ? screen.height : screen.width
// Returns height of the visible area
// It decreases if you zoom in
window.innerHeight
// Returns height of screen minus all toolbars
// The problem is that it always subtracts it with height of the browser bar, no matter if it present or not
// In fullscreen mode it always returns 320px.
// Doesn't change when zoom level is changed.
document.documentElement.clientHeight
Here is how height is detected:
var getIOSWindowHeight = function() {
// Get zoom level of mobile Safari
// Note, that such zoom detection might not work correctly in other browsers
// We use width, instead of height, because there are no vertical toolbars :)
var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
// window.innerHeight returns height of the visible area.
// We multiply it by zoom and get out real height.
return window.innerHeight * zoomLevel;
};
// You can also get height of the toolbars that are currently displayed
var getHeightOfIOSToolbars = function() {
var tH = (window.orientation === 0 ? screen.height : screen.width) - getIOSWindowHeight();
return tH > 1 ? tH : 0;
};
Such technique has only one con: it's not pixel perfect when page is zoomed in (because window.innerHeight always returns rounded value). It also returns incorrect value when you zoom in near top bar.
One year passed since you asked this question, but anyway hope this helps! :)
I had a similar problem. It had to do with 2 thing:
Box-sizing CSS3 property:
In the .height() jQuery documentation I found this:
Note that .height() will always return the content height, regardless of the value of the CSS box-sizing property. As of jQuery 1.8, this may require retrieving the CSS height plus box-sizing property and then subtracting any potential border and padding on each element when the element has box-sizing: border-box. To avoid this penalty, use .css( "height" ) rather than .height().
This may apply to $('body').height().
Document ready vs Window.load
$(document).ready() is run when the DOM is ready for JS but it's possible that images haven't finished loading yet. Using $(window).load() fixed my problem. Read more.
I hope this helps.
It is 2015, we are at iOS 8 now. iOS 9 is already around the corner. And the issue is still with us. Sigh.
I have implemented a cross-browser solution for the window size in jQuery.documentSize. It stays clear of any kind of browser sniffing and has been heavily unit-tested. Here's how it works:
Call $.windowHeight() for the height of the visual viewport. That is the height of the area you actually see in the viewport at the current zoom level, in CSS pixels.
Call $.windowHeight( { viewport: "layout" } ) for the height of the layout viewport. That is the height which the visible area would have at 1:1 zoom - the "original window height".
Just pick the appropriate viewport for your task, and you are done.
Behind the scenes, the calculation roughly follows the procedure outlined in the answer by #DmitrySemenov. I have written about the steps involved elsewhere on SO. Check it out if you are interested, or have a look at the source code.
Try this :
var screenHeight = (typeof window.outerHeight != 'undefined')?Math.max(window.outerHeight, $(window).height()):$(window).height()
A cross browser solution is set that by jQuery
Use this property:
$(window).height()
This return a int value that represents the size of visible screen height of browser in pixels.
Related
How do I get the coordinates of the top left pixel of document body in Chrome? In firefox it's possible to get with window.mozInnerScreenY + window.window.mozInnerScreenX, but not so much in Chrome?
window.screenY is the standard property. It works everywhere.
https://developer.mozilla.org/en-US/docs/Web/API/Window/screenY
If your code runs inside an iFrame it will still return the top screenY position and not the iFrame/viewport one.
Now, to measure what you are describing below (sorry, I misunderstood you) all that needs to be done is subtract the innerHeight from the outerHeight (that's give you the size of the chrome/toolbars and so, and add the screenY (which gives you the top pixel of the Chrome app, as you said).
Wrapping up, this does the trick:
window.screenY + window.outerHeight - window.innerHeight
body top
My issue is a hack for a dubious mobile browser discrepancy between the 100vh and the area hidden behind the mobile browser bars. This is a problem for any page where a full screen effect is desired.
The hack detects the difference between the VH and the actual visible viewport. However the simple js in the first code example appears to be detecting it backwards. So if the browser bar is overlaid the value should be 75 but is instead 0 -- likewise when the the browser is large it should return 0 but instead returns -75.
This can be reproduced simply by testing an iPhone with the 'develop' tool in Safari on google.com and entering this in the console.
document.documentElement.clientHeight - window.innerHeight
This seems to compute the shorter browser height with the top offset to compensate for the browser bar as being offset by 0 and the tall browser height where the browser bar is no longer covering the top of the page at -75px. This, to me, appears to be very wrong and should be 75 and 0 respectively. The below example is how I think it should work to properly offset the body tag to position elements with absolute positioning.
function fixIt(){
var offset = (document.documentElement.clientHeight - window.innerHeight);
document.body.style.marginTop = offset;
}
fixIt(); // run on resize
My extra super hacky solution it to offset the body by 75px by default and to assign the old value on vertical resize. (so when the browser bars hide, instead of 75px offset, use previous offset of 0 and save the 75px offset for the next resize). The works in Mobile Chrome and Mobile Safari, but for instance, if the link is opened in facebook where there is no browser bar and no resize events, it is offset by 75px permanently. This code is obviously insane and should be banished into the nothing.
var offset;
var oldOffset = 75px;
function fixIt(oldOffset){
offset = (document.documentElement.clientHeight - window.innerHeight);
document.body.style.marginTop = oldOffset;
oldOffset = offset;
return oldOffset;
}
fixIt(oldOffset); // run on resize
As an aside, or for further reading, here's a big complaint blog on the issue. https://nicolas-hoizey.com/2015/02/viewport-height-is-taller-than-the-visible-part-of-the-document-in-some-mobile-browsers.html I agree with the browser vendors that VH should be constant (because the reflow would be obnoxious for everything besides the actual body height) but for the top level elements like body and html tags on mobile this behavior appears to be wrong and it makes no semantic sense, plus these computed numbers appear backwards, further making this issue headache inducing.
What other solutions are out there?
I am working on a project including several draggable divs using jQuery-UI with the constrain functionality to help the user avoid stray divs hiding in the outskirts.
Now I am getting the full screen dimensions for the constrains:
var width = window.screen.availWidth;
var height = window.screen.availHeight;
And that is pretty close to what I desire. However, as all browser have the tabs and search input line on the top and often some other stuff at the bottom I am getting a bigger constrain than the actual view port. Then you say get the view port dimensions:
$(window).height();
$(window).width();
Well, that is close to but it is not 100%, because if the user has a minimized window when entering the site that view port size is going to be the constrain size. This means that if the user then uses full screen the constraint is just as big as the view port were from the start.
Then you might say: "Why not change the constrain dynamically along the way?"
Well, that could have been a possibility but this whole page idea is to fine tune the GUI and by changing the constrain size could potentially mess upp the positioning of the draggable objects. So, what am I asking for?
I am asking for a way to get the maximum browser view port size on the current users screen? No matter if the user has a smaller than max browser window ATM when entering the page.
PS. I suppose I could check which browser the user is using and by hard code remove the amount of pixels that specific browsers head-bar is using. That however is a bad solution in my book, for several reasons.
with some good suggestions pointing me in the right direction I have now understood my problem.. I think.
These two bad boys are actually doing the trick:
var width = window.screen.availWidth;
var height = window.screen.availHeight;
BUT!! I am on a desktop running windows and the taskbar at the bottom is actually overlaying the chrome browser window! This was what made me confused to start with. So... yeah. I guess that is it. I just have to live with my users beeing able to put the divs under the win taskbar. Well ok! Bye
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
Although pretty hacky, you could take advantage of the viewport units of css.
$('body').css({
'height': '100vh',
'width': '100vw'
});
var height = $('body').height(); // or innerHeight or OuterHeight
var width = $('body').width();
vw : Relative to 1% of the width of the viewport
vh : Relative to 1% of the height of the viewport
vmin : Relative to 1% of viewport's smaller dimension
vmax : Relative to 1% of viewport's larger dimension
https://www.w3schools.com/cssref/css_units.asp
You can use $(window).outerWidth() and $(window).outerHeight()
You may refer these links.
https://developer.mozilla.org/en-US/docs/Web/API/Window/outerHeight
https://developer.mozilla.org/en-US/docs/Web/API/Window/outerWidth
Mozilla & IE developers seem to have simultaneously changed the implementation of their height elements to represent the Opera implementation... which I previously did not have to worry about.
var height = (document.height !== undefined) ? document.height : document.body.offsetHeight;
When performed on a blank document now returns 0 as the height of the document. My implementation requires knowing the true client viewport to dynamically build on. Chrome and Safari are still acting as they used to.
scrollHeight, and clientHeight are acting exactly the same.
To complicate matters document.height and document.body.offsetHeight are now also taking the full height of the document into account instead of only the viewable area as they used to... I tried an old table spacing method and used a 2000px x 1px transparent andthe document height is set to 2000 now.... naturally Chrome and Safari still work as expected and only give the viewable size.
I am very desperate to fix this issue.
The viewport height is not a property of the document, but of the window viewing it. You get the viewport height from window.innerHeight.
The stuff with document is only needed as a fallback for IE, which doesn't provide the window.inner dimensions. IE (technically incorrectly) makes the document.documentElement represent the viewport, so you can get the height from its clientHeight, unless you're in Quirks Mode which (more incorrectly) makes document.body represent the viewport instead. (document.height is totally non-standard; avoid it.)
So in summary, and assuming you need to support Quirks Mode (let's hope you don't):
var height= (
'innerHeight' in window? window.innerHeight :
document.compatMode!=='BackCompat'? document.documentElement.clientHeight :
document.body.clientHeight
);
I use this, that I got from James Paldosey's site:
function getDocHeight() {
//utility function to find dimensions of page
var D = document;
return Math.max(
Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
Math.max(D.body.clientHeight, D.documentElement.clientHeight)
);
}
For FF and other non-IE browsers, window.opener.outerWidth/Height give me the info I need. For IE, I'm still at a loss, from IE6 to 8. I can't use jquery as the opener's page is beyond my control, so I can't do a window.opener.$(window). This requires the opener to have jquery 'attached' (correct me if I'm wrong).
I googled quite a bit and also searched this site, still can't find a definite neat answer.
To add:
I really need the outer size so that I can do a resizeTo(w, h) for the opened window where w and h are calculated based on a ratio of the opener's size. "resizeTo" ironically sets the outer size for IE and other browsers. I also tried a messy loads of stuff using resizeBy, not good enough.
outerWidth and outerHeight define dimensions of the browser window (including sidebar, window chrome and window [re-]sizing borders/handles). Unfortunately you cannot get these dimensions in IE - only the window viewport dimensions are available (good enough for most applications I've seen). Aka window.innerWidth/window.innerHeight.
jQuery can give you the dimensions of the current window viewport, but not other windows (eg, openers, children, etc). So you'll have to code this yourself. Here is a crude sample:
// get viewport size (without scrolling) of the given window object
function clientSize(win) {
var width, height;
if(win.innerWidth || win.innerHeight) {
width = win.innerWidth;
height = win.innerHeight;
} else {
var doc = win.document;
width = doc.documentElement.clientWidth || doc.body.clientWidth;
height = doc.documentElement.clientHeight || doc.body.clientHeight;
}
return { width:width, height:height }
}
Try it like:
var openerSize = clientSize(window.opener);
// now use openerSize.width, openerSize.height
Also note that you can't read any of these values if the given window has loaded a document from another domain (security measure).