Firefox android - window.innerheight not working properly.
Hey. I hope no one asked this question before because I could not find it. I am trying to build a website, that contains a header, a main-part, and a footer. All of them together should make up 100% of the screen size. The height of the header and footer are fixed to 100px each, so the main part has to be adjustable. On desktop this is easy accomplishable in CSS trough: height: calc(100vh – 200px). On mobile however, 100vh does not include the URL bar. Therefore, I used JavaScript. Basically, I am checking if the device used is a mobile one. If so, I use window.innerheight and subtract 200px from it. That fixes the issue, at least on some mobile browsers. And here is where the fun begins:
On brave android it works as expected.
On Edge android it works, but only after letting the page load once and then reload it.
On Firefox it does not work at all. I have a white stripe and grey scrollable space at the bottom there.
Why?
Here my Javascript-Code:
let innerHeight = window.innerHeight;
innerHeight = innerHeight - 200;
let main = document.querySelector("main");
let isMobile = navigator.userAgent.toLowerCase().match(/mobile/i);
if (isMobile) {
main.style.height = innerHeight + "px";
}
I already tried load-Events. I used the “load” as well as the “DOMContentLoaded” event, both of which changed nothing. The script itself is embedded on the bottom of the page, so the tag is already loaded when the script runs. Also, using the desktop dev tool I can see it working properly every time.
Here what I tried:
window.addEventListener("DOMContentLoaded", () => {
if (isMobile) {
main.style.height = innerHeight + "px";
}
});
That an image of my problem. Look at the bottom of the page
Related
The screen.height I am talking about is described in https://www.w3schools.com/jsref/prop_screen_height.asp
I used screen.height < 560 ? true : false to determine whether the screen height is smaller than a threshold, so I can hide some UI elements in this case.
It works fine in Chrome's simulator for mobile devices (the feature highlighted below).
By "works fine", I mean when simulating a mobile device, like setting device to be iPhone X as shown above and displaying in landscape mode, the UI elements are hidden correctly due to screen.height < 560 = true.
However, on real mobile devices like a real iPhone X, the UI elements don't get hidden, which I guess is because that it is always screen.height < 560 = false, even if it is in landscape mode.
I am wondering why is that... Why iPhone X in DevTool has a different height from a real iPhone X?
Is the simulation in Chrome DevTool not accurate? Or is it because screen.height doesn't return the correct value on mobile device?
Any hints would be appreciated!
That's because the simulator takes the screen size according to the dimensions that you are setting there. But in reality, screen.height takes the height size of the whole screen, including elements that are outside of the viewport in the device. You should use window.innerHeight to get an accurate height size.
If you log in your console screen.height and window.innerHeight on the simulator, you will get the same size. If you do this in the normal viewport (deactivating the simulator), you will get different values.
More info: Screen Height - Window InnerHeight
UPDATE
screen.height doesn't update on screen rotation, always has the same value corresponding to the screen height in portrait mode, while window.innerHeight takes the current height of the device window either portrait or landscape. Just make sure to fire this in the event when the rotation happens.
For this, you could use the Window.matchMedia() like so:
// Breakpoints
const breakpoint = window.matchMedia('(max-height: 560px)');
// Breakpoint checker
const breakpointMutations = () => {
if (breakpoint.matches === true) {
// Do something
}
}
// Run breakpoint checker if media changes
breakpoint.onchange = function (event) {
breakpointMutations();
}
// Run breakpoint checker on load
breakpointMutations();
It might be because you are missing the response meta tag. Try adding this to your head tag:
<meta name="viewport" content="width=device-width, initial-scale=1">
There are many many questions regarding resize (event) not working online, but I was only able to find one that actually reflected my exact problem but did not have an answer.
When I use inspector, my website changes from the desktop version to the mobile version when it reaches the breakpoint of <= 540px width. However, when I resize the entire chrome window, nothing happens (even though my window does get smaller than 540px width).
I'm not sure if the mobile version will actually work on a mobile as I have no way of testing that currently, but I'm unsure as to whether this is a normal thing with Chrome and the website will work perfectly well on desktop and mobile or whether I'm doing something wrong.
The related piece of code:
$(window).resize((event) => {
const windowWidth = window.screen.width;
if (windowWidth <= 540) {
$('.className1').addClass('d-none');
$('.classname2').css("width", "100%");
$('.classname3').css("left", "3%");
$('.classname3').css("width", "100%");
$('.classname4').css("width", "90%");
This is not the entire method but it basically shows the idea that css and attributes change based on window width dropping below 540px.
What I tried:
Document.resize (failed)
I really hope this isn't a duplicate, it's hard to navigate the vast number of questions out there.
The problem is not with the resize event or with browser. It's occurring because you're using window.screen.width, which is relative to the screen, not to the browser window. It doesn't matter if you resize the browser window, the screen width will not change. For example, if your screen has resolution of 1900x1200, screen.width will always be 1900. Hence, you should use window.innerWidth, or just innerWidth to get the viewport width. To know more, see this question.
Your code would be that way:
(window).resize((event) => {
if (innerWidth <= 540) {
$('.className1').addClass('d-none');
$('.classname2').css("width", "100%");
$('.classname3').css("left", "3%");
$('.classname3').css("width", "100%");
$('.classname4').css("width", "90%");
An example of working code (open the snippet in full page and resize it):
$(window).resize((event) => {
if (innerWidth <= 540) {
document.write('It\'s working.');
}
});
<html>
<body>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</body>
</html>
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'm having trouble with an animated scrollbar. The intended behaviour should be on clicking the nav-button, scroll with ease to the end of the page(and a little break near the end).
Now the problem on PC works perfect. On android device (I tried my phone), the scrollTop value and the ($(document.body).height() - $(window).height()) do not match. There is exactly 55px less with the scrollTop thus acting all sorts of strange... Also sometimes it works sometimes it doesn't. I've figured it has something to do with the browser bar collapsing and upsetting the value...but i can't figure it out.
I've tried the following: initializing the variables on scroll event, i've tried vanilla js that didn't work. Need help :) for reference http://www.developer.morningmood.org , also i've printed out the values on bottom of the page if it helps. Here's the code.
contactF = Math.floor($(document.body).height() - $(window).height());
$("#cont").click(function(){
if ($(document).scrollTop() < contactF && flagScroll==true){ //flag stops other buttons from beying pushed
flagScroll = false;
var inter = setInterval(function(){
var doc = $(document).scrollTop();
if (doc == contactF){ // this is the final desired position
clearInterval(inter);
flagScroll = true;
pix = 10; //pixels to jump
return;
}
if (doc >= contactF-50){ // this is a break on aproach
pix = 1;
}
$(document).scrollTop(doc + pix);
}, 10);
}
})
EDIT: also to find the bug, you nedd to scroll from the top of the page all the way to the bottom, if from the top of the page you just push the contact button it works. but if you scroll it doesn't, it upsets the value...
Had the same exact problem and spent a whole day to figure it out.
You are right about the address bar collapse on Android chrome messing it up. Turns out the jQuery function $(window).height() always reports the viewport height that is before the address bar collapses. To get the correct value, use window.innerHeight instead. You can find more information about URL bar resizing here https://developers.google.com/web/updates/2016/12/url-bar-resizing
You can also find people asking similar questions regarding the safari address bar auto-hide, the solutions are similar. Mobile Safari $(window).height() URL bar discrepancy
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.