JS - Safari on iOS - How to get viewport scale property - javascript

On Chrome, I can get the viewport scale by looking at window.visualViewport.scale it is available on Safari, however, it seems that window.visualViewport is not defined on older versions of Safari on iOS.
Is there any workaround?

Firstly, you need to get viewport width by using clientWidth or innerWidth
var viewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
Then, you need to get actual screen width
var screenWidth = window.screen.width
Then, viewport scale is on your hand
var viewportScale = screenWidth / viewportWidth

According to caniuse.com visualViewport.scale should be available in Safari for iOS from version 13.0 which was released 19 September 2019. Have you updated yet?
If you really need to support older Safari for iOS, and also if you have no need to measure scale right at the page load, you can try to catch touch events and guess/calculate scale by yourself.
If you're going to really desperate, you can try to "invent some bicycle". For example (just the concept): create and measure 2 <div> right inside <body>. One of them width: 100vw; and another width: 100%; (this actually isn't needed since blocks already will be 100% width of parent block). The trick here would be in different units. 100vw should be always 100% of the viewport, when 100% should stretch for maximum available width. Measure the difference between those 2 blocks and you can calculate scale. Be aware of those tricky margins/paddings and maybe of the landscape.

Related

How to set width and height of canvas to all height and width of browser without overflow?

I want to make a canvas with width and height of document without scrolls, but I don't know how to do this. I tried:
canvas.width = window.innerWidth;
canvas.width = parseInt(getComputedStyle( document.body ).getPropertyValue( 'width' ));
canvas.width = document.body.offsetWidth
canvas.width = document.body.clientWidth
But I got 1-20 unused pixels that I can scroll, also I can't reduce width and height by fixed number of pixels - different browsers show it differently.
Fixed by "display: block", canvas elements aren't blocks by default.
if you're asking how to make an element 100% of the viewport's width and height, you can use CSS...
#selector_id {
width: 100vw,
height: 100vh
}
window.innerWidth gives you the whole width inside the window frame ignoring the scroll bars.
document.body.clientWidth gives you the width inside the vertical scroll bar - if present.
These both work on current versions of Safari and Chrome - I just gave them a quick try.
Both should work on all modern browsers check here for
window.innerWidth and here for document.body.clientWidth.
I'd be interested to know any circumstances where these don't work as advertised.
(Of course if you executed the code exactly as you've shown it you would end up with just the value of document.body.clientWidth. I'm guessing you meant you tried each of them in turn.)

Understanding orientation, aspect ratio and CSS pixels on mobile devices

For my current project, I need to optimize a page layout in landscape mode for mobile devices. Can you help me to understand the different ways that the browser window size is measured?
I am working with an Android smartphone with hardware pixel dimensions of 720 x 1280 pixels.
Portrait Mode
In portrait mode, when I use JavaScript to get the document.documentElement.clientWidth and ~Height, I get the result 980 x 1394.
When I use the following CSS...
html {
height: 100vh;
width: 100vw;
}
body {
height: 100%;
width: 100%;
margin: 0;
}
... Chrome Development Tools reports that the size of the body is 980 x 1546.
Landscape Mode
In landscape mode, things seem even more complex. In my test, I explicitly CSS set the dimensions of the whole <html> tag to 100vw x 100vh, and the body width and height to 100%.
However, JavaScript reports the clientWidth and clientHeight as 980 x 460, while Chrome Development tools shows the dimensions of the html and body elements as 980px x 556px, although neither of these elements fills the screen width or height.
A <main> element whose width is set to 200vh and whose height is set to 100vh fills the entire width of the screen in landscape mode, but leaves a gap in the vertical direction, despite the fact that Chrome reports it to have dimensions of 1112px x 556px.
It would also be very helpful to know what exactly the different dimension properties are measuring, so that I can understand how they should be used.
EDIT:
To reply to #Kaddath: No, I had not configured a viewport meta tag. When I add the tag <meta name = "viewport" content = "width = device-width, initial-scale = 1.0">, the dimensions change. In particular the `` clienttWidth in portrait mode becomes the screen width in hardware pixels, divided by the devicePixelRatio, which makes perfect sense. The clientHeight appears to be the height of the screen in CSS pixels, minus the height of the app bar and the built-in button bar.
In portrait mode, the values for clientWidth and clientHeight are not so easy to explain.
To better understand how browser work on different situation try to call you function with
setTimeout(showSize,300);
onresize doesn't fire correctly on all browsers.
Also try window.outerWidth and window.outerHeight.
It is very much to explain but you will learn.
You can also read https://developers.google.com/web/fundamentals/native-hardware/fullscreen/

Retrieving viewport height of screen in mobile browsers with jquery

I'm attempting to get the viewport height in mobile browsers WITHOUT the height of the browser bar but all of the solutions I've attempted have come up short.
What others have suggested is using the below, however it does not work for me. I still get a blank white bar at the bottom of the window when scrolling
var screenHeight = window.innerHeight;
$('.mobile-nav-wrapper').height(screenHeight)
I believe what you are looking for is scrollHeight
The scrollHeight property returns the entire height of an element in
pixels, including padding, but not the border, scrollbar or margin.
You can try this:
document.body.scrollHeight
Solution 1:
I don't have an answer using jQuery. But using a plain/vanilla JavaScript wouldn't cause any issue :).
Following script allows you to detect the Viewport size (height and width) reliably.
https://github.com/tysonmatanich/viewportSize
Sample usage:
<script type="text/javascript">
var width = viewportSize.getWidth();
var height = viewportSize.getHeight();
</script>
I have used it in couple of projects, were i have to re-initialize some widgets based on current Viewport width/height rather than using window width/height (Window width/height calculation isn't consistent in all browsers - some include scroll bar size 16px as a part of window width and some doesn't).
Sample Test page:
http://tysonmatanich.github.io/viewportSize/
Solution 2: (Just for reference - Not an answer to OP's question, though it is related so I thought that it can remain)
Well modernizr has a very good addition Modernizr.Mq. Through which you can cross check which break point range you are in...
if(Modernizr.mq("(min-width:320px)")){
//Do job 1
}
else if (Modernizr.mq("(min-width:768px)")){
//Do job 2
}
or
based on height
Modernizr.mq("(min-height: 800px)")
http://tysonmatanich.github.io/viewportSize/

Can't reliably detect scroll bottom between iPhone portrait and landscape modes

I'm trying to detect when a user has scrolled to the bottom of the document. My current solution works fine in desktop browsers, and with Mobile Safari in landscape mode (with a 1px variance that I can't yet explain). However, I'm getting a completely different result for Mobile Safari in landscape mode.
I have a working example here: http://dl.dropbox.com/u/5634676/checkbottom.html
The detection routine boils down to:
if ($(window).scrollTop() + $(window).height() >= $(document).height())) {
// Bottom reached
}
Can you explain the difference between the two modes and help me reliably detect when the user has scrolled to the bottom of the document?
Update
I've updated the linked example fixing the bug pointed out by theflyingbrush. The results for landscape and portrait modes are now closer together (but there is still an as yet unexplained variance of 52px). Importantly though, for both portrait and landscape modes scrolling to the bottom of the page is still not detected.
I had the same issue on IOS mobile devices. Replace 'document' with 'body' fixed my issue.
if($(window).scrollTop() + $(window).height() > $('body').height() - 200 )
Also, it is better to check if 'near' bottom of the screen.
The height of the window changes when the device orientation changes, invalidating your windowHeight var stored on doc ready. Update it by listening for the orientationchange event and recalculating the window height. Something like:
window.addEventListener("orientationchange", change);
function change(){
windowHeight = $(window).height();
}
Edit: Confusing this, because it also involves the viewport scale. Here's a link to a working version: http://appunit.co.uk/scroll
You need to account for the height of the address bar in your calculations, because $(window).scrollTop() returns 0 until the address bar is scrolled offscreen. So, add the address bar height (60px) to scrollTop to get the distance scrolled. This is made more complicated if you haven't set a viewport meta tag in your html specifying width=device-width. In that case the viewport will be scaled from 320x356 to 980x1091, and the amount of virtual height the address bar takes up is scaled also. Summary:
var scaleFactor = ($(window).height()/356).toPrecision(2);
// toPrecision(2) prevents rounding error..
var addressBarHeight = 60 * scaleFactor;
// and when calculating scrollTop
var scrollTop = addressBarHeight + $(window).scrollTop();

How to make window.innerHeight work on mobile devices when zooming?

window.innerHeight
Yes, it will return the value of the browser's height on a mobile device. However, the problem comes (on some browsers) when a user tries to pinch to zoom in or zoom out. The value will not adjust properly and instead still return the full length of the page.
Let's say it was 500px when loaded. The user then zooms in and the height is now 200px. However, the value is still returning 500px.
Does anyone know a method to fix this? Been searching forever.
The way I fixed this was to remove any resize callback in my code. Sounds weird, but it worked for me.
Check out the accepted answer in this link:
Detect page zoom change with jQuery in Safari
If your want innerHeight, may be get original width and then zoomed width, get zoom ratio and then calculate the new Height (after zoom).
This worked for me. The first thing I do is grab window.innerHeight and window.innerWidth from the dom when the page loads so I get the original values and store them in javascript variables. Then in my window.onresize event handler I do this.
var height = null;
var width = null;
if (window.orientation && window.orientation == -90) {
height = myOriginalHeight;
width = myOriginalWidth;
}
else {
height = myOriginalWidth;
width = myOriginalHeight;
}
doCallbacks(width, height);
My app resizes a lot because I attempt to write one ui for all screen types. According to my testing with the app this works on ipad and andriod and all the resizing works when zoomed in or orientation changes which can sometimes cause zoom to occur.
The interesting aspect of this is mobile browsers never actually change screen sizes as they are fixed, they just zoom. But if you resize to original width/height and handle orientation this way it seems to work.

Categories

Resources