Understanding orientation, aspect ratio and CSS pixels on mobile devices - javascript

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/

Related

Scaling an iFrame depending on window size and content size

I have a dynamically generated iFrame on my page that loads a website using a variable object.
All that is well understood. My challenge now is that in some cases, say if I am viewing on mobile, the frame width exceeds my mobile device width.
// STATIC VALUE
let screenSize = {
"height": window.innerHeight,
"width" window.innerWidth:
}
// DYNAMICALLY GENERATED VARIABLE
let frameValue = {
"url": "https://example.com",
"height": 913,
"width": 1600
}
//Using this variable, the iframe property is set as follows using javascript
$('#dynamicFrame').attr('src', frameValue.url);
$('#dynamicFrame').width(frameValue.width);
$('#dynamicFrame').height(frameValue.height);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- HTML DYNAMIC iFRAME -->
<iframe src="" id="dynamicFrame" frameBorder="0" width="100%" height="100%" scrolling="auto"> </iframe>
Need:
I would like an algorithm (or perhaps some code) to perhaps scale or zoom the iframe whilst keeping its aspect ratio.
Meaning I want the content to of frameValue.url (example.com) to load in the iframe as it would while considering frameValue.width & frameValue.height.
Notes:
I don't mind having the iframe look smaller or have dark bands around the edge just like when you watch videos on a mobile device or use zoom or Microsoft teams on a mobile device whilst the person sharing the screen is on a desktop device.
Please feel free to comment if you need further explanation. Thank you.
Is there any reason you aren't using a CSS solution? It'd be a much cleaner solution than setting the height/width attributes.
#dynamicFrame {
/* Swap for your desired aspect ratio */
aspect-ratio 16/9;
width: 100%;
height: auto;
}
Depending on the screen size and orientation, one of the following formulas may be useful.
NB:The orientation can be determined using the dimensions provided. i.e landcape = width > height
let scale = 0;
// If the window is potrait and the frame is landscape orientation
scale = screenSize.height * (1 / frameValue.height);
// If the window is landscape and the frame is potrait, one of the following applies.
scale = dimensions.height/dimensions.width).toFixed(2);
// OR
scale = dimensions.width/dimensions.height).toFixed(2);
// Set the iFrame Dynamic Scale Value
iframe.style.transform = `scale(${scale})`;

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

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.

how to set a minimum width for your site / viewport and have browser scale if the width is below that

I'm trying to wrap my brain around viewports / scales. I have a site I have to program, and the design I've been given is responsive, but it really doesn't work if the device's width is below 420px.
At anything below 420px, I'd love it if the browser would render the site as if it were 420px wide, just zoom everything out, but I can't figure out how to do this.
I've seen how you can dynamically change the meta viewport tag, but when I do this, it doesn't seem to have any affect, and I'm not sure that's the best way to approach what I'm trying to achieve.
At any rate, this is what I tried:
var minBP = 420;
//ww = window width
if (self.ww < minBP && lastScreenWidth > minBP){ //site is smaller than minimum allowed width, modify viewport
var viewportString = "width=" + minBP + ", initial-scale=1.0";
$('#blackrock-viewport').attr('content',viewportString);
}
Anyone know how to render a scaled-out 420 viewport width when the browser drops below these dimensions?
well you can do that in css by using Media Queries it allows you to manipulate evrything in diffrent screens
for exemple if you want to change the width of div in 420px screen you can do this :
#media (min-width:420px) {
div{
width:50px;
}
}
You can just use media queries to target specific elements on specific screen sizes.
For your situation, you just have to limit your wrappers width to your preferred size.
Supposing that you have a div that wraps all your page, let's say .wrapper.
#media screen and (max-width:420px) {
.wrapper{
width:420px;
}
}
Of course, you can do this also without media queries by just setting the min-width property of your wrapper.
.wrapper{
min-width:420px;
}
But I suppose that with media queries you are more flexible.

find screen dimensions in inches not pixels using javascript

I was reading many questions on SO regarding best ways to detect screen size in pixels which is ultimately dependant on resolution to find the actual screen size.
I know some mobile devices have small screen (say 4inch) yet the resolution is high. While some devices r having large screen (say 7inch tab) yet the resolution is low.
So when you want to display your page to the user, you really need the screen size in inches or centimetres to give the best view comforting the eyes.
So I ask:
Is there away to find out screen size of the device in inches not pixels ?
I know it can be, provided that we know the resolution! !Bec we can calculate the size from screen width and height
Appreciating any idea!
once you have got the screen resolution in pixels, you can work out the dpi with a hidden div:
<div id="dpi" style="height: 1in; width: 1in; left: 100%; position: fixed; top: 100%;"></div>
js
var dpi_x = document.getElementById('dpi').offsetWidth;
var dpi_y = document.getElementById('dpi').offsetHeight;
then work out the resolution in inches:
var width = screen.width / dpi_x;
var height = screen.height / dpi_y;
Example
Now, as far as I can tell there is no sure-fire way to accurately get the screen width of a device. Everything (including inches, 1in == 96px) is based in one way or another on screen resolution.
Now, I know this may not be the fix-all for everyone, but hopefully it helps a few people out there. It helped me, since I wanted my page to behave differently for mobile users, and my initial plan of attack was going to be based on screen size.
What I ended up doing was replacing the line
if (screen.height <= 768)
with
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent))
As a disclaimer, I should also mention that this was from an answer that is a few years old now, so some devices may not be covered.
Source: https://stackoverflow.com/a/26577897/8082614

Using returned viewport queries as SASS variables

I just don't see anyone talking about this exact issue out there. Looking to have site fit any screen exactly with no scroll. Certain elements being fixed ratio (logo, video players, etc) means other areas have to expand/contract amorphically to accomodate their fixed behavior that can't ever go past 100% width or height. Difficult to explain, but the behavior in sassmeister gist below shows it working. To do this, I need to be able to define widths in terms of heights, and vice-versa (width = 56.25% of height, etc)
I can make it work using vh, vw, vmin, a bunch of calc functions etc... but browser support is patchy, and I'm unaware of a polyfill to smooth all that out. My vh, vw, calc solution below:
http://sassmeister.com/gist/3dee56a4092a86cf070a
Only other pure css I'm aware of that even begins to address this is the percent padding trick tying padded height to parent width, but this alone isn't enough. I need to be able to use min, max statements, and tie width and height going both ways.
So... unless I'm mistaken, #media queries only ever return true/false, so they can't provide an actual viewport measurement to use, right? That's what I really need... a pixel accurate measurement of the available viewport height and width.
What's the solution here? Should I use javascript to get those exact dimensions, then do all the arranging in javascript? Use JS to get the variables, then pass them on to the css?
Something like this: https://gist.github.com/scottjehl/2051999 and a method to import those returned values into css should work, no? Is that slowing the site down too much to have the js call first before anything else happens?
Also, need to find the right way to do all these calculations. Should I just be using javascript to do all the calcs and leaving stuff like the following out of css completely?
$gutter: calc(((100vh + 100vw) / 2) * 0.04)
Then using that variable inside another function:
$column-width: calc(100vw - (1.7778 * (100vh - 2 * $gutter)) - 3 * $gutter)
You get the idea. I think I'm nearing the end of what I can do with the css. JS solution? Hybrid? Something else?
thx.
It sounds like media queries are what you're looking for.
You can use the following to target screens with a max width of 1200 px and a min width of 800:
#media all and (max-width: 1200px) and (min-width: 800px) {
//some css here
}
Check out the way bootstrap-sass implements containers here.
Also check out the other SO answer about media queries.
You can even specify landscape and portrait layouts.
#media (orientation:portrait) { ... }
Or aspect ratio:
#media screen and (device-aspect-ratio: 16/9) { ... }
I hope this helps. You can use some of those fancy gutter calculations inside of/with media queries and that should simplify things a bit.
This javascript will return the screen height:
var x = "Total Height: " + screen.height;
document.getElementById("demo").innerHTML=x;
Width:
var x = "Total Width: " + screen.width;
document.getElementById("demo").innerHTML=x;
Some JQuery:
$(window).height(); // returns height of browser viewport
$(document).height(); // returns height of HTML document
$(window).width(); // returns width of browser viewport
$(document).width(); // returns width of HTML document

Categories

Resources