Viewport height in mobile changes - javascript

Ok, this isn't a new problem. I see a few people here have asked about it but I'm hoping maybe someone has a new answer. It seems like this should be a more common issue.
When an element's height is set to 100vh (100% of the viewport height), it works fine. However, if you scroll down (at least on Android) the address bar goes away and changes the viewport height. This suddenly shifts the page as the 100vh height changes.
The solutions I have seen involve javascript. This might not really be a problem in my particular case but I am hoping maybe there is some CSS solution to this.

Related

What's the width of a screen? 100vw vs innerWidth vs visualViewport.width vs screen.width (React)

As you could imagine, I'm trying to make my webpage responsive and mobile friendly.
I have an outer container on which I set the width dynamically using this hook (window.innerWidth). So to test if the page is responsive I open up Chrome-devtools and start making the devtools wider:
Sure it's a little jumpy but it scales correctly, as expected. The problem starts when I open up to do the same in the responsive tools:
Suddenly the whole page scales down? Also, it's hard to see but I'm logging window.innerWidth and it's not changing as I'm changing the width.
So I try it out on my cell-phone and the the behaviour is really unexpected:
On load it looks ok
Flip the phone, still as expected, but when I flip it back???
This crazy effect happens, I mean now it looks like window.innerHeight is having some trouble as well? Because the container with the gray background color has it's min-height set to window.innerHeight. And if i try going to some other page of the app and then back I get this:
It's a zoomed in version of the last image. I can pinche-zoom out from it.
So I google around and it looks like I find someone with the same problem there's a detailed answer suggesting I should use window.visualViewport.width instead. So I try it out:
Main differences, the resizing seem's a little jumpier. I'm also logging window.visualViewport.width and it is changing, but only slightly and it's not corresponding to the responsive-width that's shown above the screen.
But most importantly, it's unfortunately not fixing the problem of weirdly resizing the entire screen, and the unexpected behaviour on mobile remains. (should be mentioned that this one too, works as expected if I'm not in "responsive mode" and just resize the window.
So I spot another answer further down suggesting to use window.screen.width instead, so I try it out:
Which introduced a whole new type of wonkyness? It seems to scale correctly, but down at around a few pixels above 300 it starts to just cut-off a piece of the header while making the container (which should be the width of the screen) smaller at a faster rate than the screen?
This seem to be related to the fact that the header has the css:
grid-template-columns: 130px auto 130px;. If I lower the 130px-value, the point at which the header gets cut off lowers as well. I suppose making the screen go below the headers min-width causes some (in my opinion) really unexpected behaviour.
Though the console log (now logging window.screen.width, now correctly prints the width reported by chromes responsive tool. The bug can be seen in my phone as well
I guess my phone must be a few pixels below 300 in width. Interesting fact is that using 100vw displays exactly the same behaviour as using screen.width.
It's also interesting to look at the difference between screen.width, innerWidth and visualViewport.width. If I set the size of the responsive window to 500px and reload the window. All of them evaluates to 500px. If I set the screen to any value below the threshold where screen.width starts to cut off a piece of the screen.
screen.width evaluates to the width of the responsive window.
innerWidth and visualViewport.width will both evaluate to 309px (which I assume is the minimum functional width of the header.
If we look at how innerWidth and visualViewport.width looks on my phone:
On both visualViewport.width and innerWidth we can see a much smaller but similar line to the one on screen.width (here it can be seen on a zoomed in screenshot).
First solution
So the first and most straight forward solution would be to use window.screen.width (or 100vw) and simply make sure that no element ever push themselves outside the width of the screen.
But wait, another solution has appeared!
By looking at a comment to an answer of the previous question I see that someone solved it by changing the the viewport meta-tag from
<meta name="viewport" content="width=device-width, initial-scale=1" />
to
<meta name="viewport" content="width=device-width, minimum-scale=1" />
All alternatives, screen.width, innerWidth and visualViewport.width all now behave identically to each other and as desired:
They all log the correct width of the responsive window, the page on my mobile also works. If you look closely you can see that the header does get cut off a little when the screen goes below the 309-threshold. But with this solution it seems like the page breaks a lot more gracefully than in first solution.
So if you've already solved the problem, why are you posting this question?
Well, as you might have understood by now, I love this problem more than I love the solution. That is, I would really like to know WHY this solution works? So even though my "practical" problem is solved I'm really curious as to a few remaining mysteries:
Why does resizing the window (first video) behave differently from resizing the "responsive box" in chrome dev tools?
Why does the bug appear on my mobile when I tilt my phone, and then tilt it back again? (third picture)
Why, when I (on the phone) go into some page and back again, is the screen super zoomed in? (fourth picture)
Why does innerWidth and visualViewport.width continue to print the same value when resizing the responsive window.
Why do they weirdly scale down the whole screen instead of changing the size of the screen in the expected way (are they for some reason zooming out when making the responsive window smaller? Is that why setting minimum-scale=1 solves the issue?)
Why does screen.width behave differently from innerWidth and visualViewport.width? And why does it cause such a weird white-space effect when going below the minimum width of the header?
Are there any reason one wouldn't want to set minimum-scale=1?

Detect if the viewport width is bigger than the visible width on Mobile Safari using javascript

I have an element with position fixed (pinned to any corner) on a page (which I do not necessarily have control over the meta viewport tag - it is an embedded widget for third party sites). On Mobile Safari when the user pinch zooms the page at a certain point the viewport becomes larger than the visible area. At that point the fixed position element stays attached to the viewport and is not necessarily in the visible area.
I would like to compare two widths: the width of the visible area and the width of the viewport. I believe the size of the visible area is window.innerWidth. I am not sure how to measure the viewport.
I have been trying to see the relationships between:
document.documentElement.clientWidth
screen.width
window.innerWidth
window.outerWidth
...But have not been able to see anything obvious.
This is butt ugly but it does show some code that almost works (view on iOS to see it working. Use a desktop and click edit at top right of page to see or edit code):
https://jsbin.com/jopamu (iOS only)
The trick with the "overzoom" calculation is nasty but it does compensate somewhat for the multiple viewport zooms. It is a complex problem to solve because there are competing issues:
pinch-zoom
zoom due to input focus
the "position:fixed" zoom
potentially the OS (accessibility) zoom
The possible solutions I have found are:
Position the menu using the calculations above and position:absolute - updating the left/top in onscroll event. Has ugly juddering (can improve a little by hiding and only showing when zooming/scrolling finishes).
Position the menu using position:fixed but change the left/top to correct the menu position as zooming/scrolling occurs. Much less judder but I couldn't quite get it 100% reliable (some race condition).
Not suitable for your case (and highly unrecommended due to risk of breaking things): you can prevent pinch zooming and iOS10 double-click zooming by cancelling default on touchstart. Difficult because it needs many other workarounds so normal touch works, and needs synthetic scrolling and zooming (but has ugly side effects such as preventing scrolling working sometimes and also interferes with accessability e.g. if voice accessability turned on etc etc).
If you just want to see the widths then use the older version:https://output.jsbin.com/jopamu/6

Sticky footer hack is close, any tips to get me closer?

Here's the website: http://www.square1cards.com/
I'm trying to retrofit a responsive design with a sticky footer and so a lot of the CSS options we're incompatible and the fixed option really didn't satisfy either.
Since my top content (for the homepage) is a fixed height, through javascript I tried simply changing the top margin to the difference between the window height and that fixed value (when window height is greater than the fixed value). A crude hack.
If you slowly resize the browser height it works fine but when you QUICKLY resize the height it causes the footer to jump off the screen slightly. If I can resolve that, I should be ok. Any ideas?
I found Matthew James Taylor's tutorial to be very useful. It worked for me using only HTML and CSS. I would highly recommend that approach instead of using JavaScript.
http://matthewjamestaylor.com/blog/keeping-footers-at-the-bottom-of-the-page
I'm not sure what exactly you're trying to achieve, but I'm covering all known sticky footer techniques, or the techniques for what people (sometimes erroneously) call sticky footer, in this tutorial. Let us know if it helps you.

Rendering bug in WebKit browsers

In the project I currently work on we experience very strange rendering issue. The worst thing is that this issue emerges completely spontaneously and after several days of testing we haven't managed to find the sequence of actions wich would reproduce this issue. Here is an explanation of how this bug look like. Here is a screenshot of how the page should look like:
But instead of this after some manipulations content block pops up so only the part of the content is visible and its look like:
The most strange thing is that such a position of the block is not based on values of CSS properties as shown by Web Inspector.
As you can see the CSS properties are ok, while the position of the block is not. This fact suggest me that it could be some rendering bug of the WebKit engine
The project is built using Ext JS 3.4 and it is a classical one-page web application. This issue was seen in the last versions of Chrome and Safari on Mac OS 10.7/10.8. Though due to the spontaneous nature of this issue it might be present in other browsers and platforms too.
Any piece of advice on how to debug such issues or how it could arise is welcome.
Please check if any of your code or Ext JS's code is using scrollIntoView method, we have seen similar issue when scrollIntoView is called on any element that does not have overflow set to auto and it is inside an clipped element that is probably placed relatively positioned.
It seems bug in webkit because it scrolls clipped element which is not happening in other browsers.
I also see two elements in same hierarchy which has overflow set to auto. And scrollIntoView is scrolling wrong element.
Chrome and safari on Mac are having problems with scrolling. If the element has been scrolled and the content changes, the scroll position is kept even if the content is not high enough to require a scrolling.
The work around we have found in our application is to resize the container (the one that has the scroll) so that it has the scrollbar (or else you cannot play with the scrolling properties) and then reset the scrolling, and the height.
$(container).css('height',1).scrollTop('1').css('height','');
Here is how we do it in jQuery. You will not even see a flickering :)
I am not sure if it is the problem, but this thing kept us on our feet for a while.
i went through the same problem while working with a sencha touch 2 app and because thats same as ExtJS i have a solution for you
this probably is a bug in the framework and this happens when the ExtJS renders the application before the browser populates mayb the correct window.innerWidth and window.innerHeight and thus the viewport cannot take the correct width and height. this also explains the randomness of the event. This becomes more prominent when used on mobiles probably because of the limited resources and slow response.
the solution that i took to handle this mayb isnt a good one but i couldnt find a better one considering is a glitch in the framework itself
i poll for the correct height and width of the browser for around a sec after every say 100ms for the correct height and width of the window and if i find that the height OR width of the viewport isnt same i re adjust it. because you are working with ExtJS and app would run on high powered systems(as compared to mobile phones) i would recommend a smaller interval and then to be safe a larger time period to which it polls.
heres the code that i use currently edit according to your needs
var aId = setInterval(function () {
if (Ext.Viewport.getWidth() !== window.innerWidth || Ext.Viewport.getHeight() !== window.innerHeight) {
Ext.Viewport.setSize(window.innerWidth, window.innerHeight);
clearInterval(aId);
}
num = num + 1;
if (num > 10) {
clearInterval(aId);
}
}, 100)
i currently use this code inside the launch function of the app. but you can also use this inside the show event of the viewport for which you should keep the interval time to minimum possible to avoid any lags.
with this if you think this app might be used on devices where the window height and width would be changed by the user (like that of mobile browser when the orientation changes or if you think user would change the height and width of the browser window). then just copy & paste the same code piece inside the viewports resize event so that it also polls and resizes viewport when the size of the viewport changes.
Did you try adding a clear:both; block after the toolbar div ?
<div style="clear:both;"></div>
#bjornd it's pretty hard to debug without any code :)
Is the toolbar positioned and has the content an ID that's called in the URL?
In other words: is there some link (e.g.) that triggers #content and has no preventDefault() etc? This would scroll the page probably.
I dunno, this was the first thing that came to mind.
It could also be the toolbar content that is (for some reason) no longer cleared or some change in the content's top position (relative to another changed/removed element?)
Try and create a stripped-down test-case that contains the simplest of code but still triggers the bug. If you post that (through e.g. a Fiddle etc) we can have a proper look.
It might be a css issue;
I've had a similar issue using equal height divs by setting a padding-bottom: 99999px; and margin-bottom: -99999px;. Which workes fine in all cases, except when you use hashtag anchors to jump to a div further on the page. Jump down.
In that case the top of the page clipped and started with the div I wanted to see.
Since you say the problem is pretty hard to track, this might be something to have a look at. The solution was to remove these 2 css lines and use another method of setting div heights.

Web page fit to resolution

I built a new .Net website which will fit nicely on 1200px width resolution.
The problem is that some of my users will browse this website with 1024px width.
Is there a way to fix this problem quick without changing all the design of the page? For example, to put some javascript that will do the trick.
Please keep in mind that the top banner of my site is 1200px wide, and I don't need to support less then 1024px resolution.
Thanks a lot.
It all depends on how 'properly' your web site was designed. You might need to change a few widths for the main containers (hopefully divs) and the whole content will reflow nicely.
However, if your website contains fixed widths for individual elements, or if there are some images / background images with fixed width, then you will have to amend them as well.
Relatively / absolutely positioned elements will need to by amended as well.
There is no silver bullet 'make my page look nice in smaller resolution', if that's what you're looking for.
I would use javascript. I'd check user's width with document.width, then use jQuery's css() element to change what's needed.
If you really don't need to support users with horizontal resolutions less than 1200px, then why not just let them have the horizontal scrollbars?
Wrap the whole structure of the site in a (div) container that has a min-width: 1200px and be done with it.
Otherwise, if you can't stomach some users having horizontal scrollbars and you really want to maintain the beauty of the site, then you really need to get out of your way and re-design the site in a way that it gracefully degrades in lower resolutions. It definitely is not easy but it can be beautiful.
Here's an article from alistapart that discusses the techniques involved.
You can use the following CSS:
min-width:600px;
max-width:2000px;
this code will set the webpage to all resolutions between 600px to 2000px.

Categories

Resources