Mobile Webpage with fixed width to support multiple devices - javascript

I came to a problem on the later stage of a project for a mobile page. Client asked to support both iPhone and various android mobile devices instead of supporting iPhone only.
The mobile page was written in XHTML, with html page width 640px, and its elements have width,e.g. 500px, %20... so the page look great in iPhone's safari with the following viewport, but ugly in other devices's browsers.
<meta name="viewport" content="user-scalable=no, width=device-width, target-densityDpi=device-dpi,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5;">
I was trying to solve the problem by playing with viewport, but have being struggling for a long time. My idea is about the initial-scale, can someone suggest a way to dynamic assign this value = device-width/640 ?
Thanks

You should just use:
<meta name="viewport" content="width=320">
Why 320? It's because although the iPhone 4's screen is 640 pixels wide in portrait, it's a "retina" display with twice as high effective dpi as desktop screens. Hence it has a window.devicePixelRatio of 2, which means that its device-width is only 640/2 = 320 CSS px, i.e. each CSS px takes up a 2x2 square of physical device pixels (see this article on QuirksMode for more details).
This 2x scaling is very useful, because for example you can set font-size:14px and the perceived size of that text will be the same as if you viewed 14px text on an iPhone 3G (since it will actually be displayed using 28 physical device pixels on the iPhone 4, which compensates for the higher dpi). If instead your font-size:14px text was shown using only 14 physical device pixels, it would look tiny on the iPhone 4 (half the size that it would on a iPhone 3G).
Now, there is a consequence of this: your site has to be designed for 320px width, not 640px. But that was already true, since iOS has never supported target-densityDpi=device-dpi, so by putting width=device-width you were effectively putting width=320 anyway.
So why use width=320 instead of width=device-width? Since you say that your site is a fixed-width layout, then with width=device-width it is likely to look bad if it is shown on different size devices, for example you might see a white margin down the right hand side on wider devices, whereas with width=320 the browser will scale it up to fit the device's screen width (it may therefore look somewhat enlarged, but that's probably better than having a white margin).
However, please just consider this a stop-gap measure: it would be much better to keep width=device-width, and modify your site design to be flexible instead of fixed-width (for example set width:100% on your divs and images instead of width:320px). For more information, see http://www.html5rocks.com/en/mobile/responsivedesign/
Finally, you can keep the ", user-scalable=no" term if you really don't want the user to be able to zoom in and out, but for accessibility reasons it's often better to omit this, unless you're designing something like mobile maps.google.com, where you're manually handling pinch zoom gestures and you don't want to browser to interfere.

Related

Change viewport-hardware pixel scaling

How do I make the pixels of the content of my browser (chrome 44.0.2403.155 m) coincide with those of my physical screen (laptop computer)?
I'm totally new to front-end development and just painfully discovered, after spending hours generating an image of a specific size in pixels, that the (virtual?) pixels in the browser's screen do no coincide with those of my physical screen hardware.
There's a lot of material out there about responsive design but there is not UX consideration to make in what I am doing. What I need is the pixels in my browser to coincide with those of my screen.
I tried both
<meta name="viewport" content="width=1920"> (1920px is the width of my screen)
and
<meta name="viewport" content="width=device-width, initial-scale=1.0">
but I don't see any change, not even when I play with those numbers (Is this viewport meta tag intended only for mobile devices?).
I also learned that there exists the window.screen object and that window.screen.height and window.screen.width but they are read only.
After trying a LOT of things I found the answer:
The reason why I didn't have a 1:1 scale between my browser's pixels and my physical screen's pixels was that my windows 10 was set to scale everything:
Taking this X% setting, the browser sets the width of its screen as
(Physical Screen Width) / X%
In my case, that is 1920px / 150% = 1280px
After changing this setting to 100%, I get 1-to-1 correspondence between browser and screen pixels.
I also found here in StackOverflow that the viewport metatag does not affect a non-mobile (desktop, laptop, ...) device browser. I would like I had found this answer in an official document, though.
Does Viewport affect desktop browsers?
How do desktop browsers handle mobile meta tags?

How does viewport detection differentiate tablet from phone?

Everywhere I look, people keep saying stay away from UA-sniffing, even JQuery dropped that feature...
So how in the world does viewport-detection fill this gap of tablet vs phone (since newer models overlap in resolution)?
Can anyone explain how viewport detection is THE WAY to go on this...
According to your comments, what you really want to be doing is setting
<meta name="viewport"
content="width=device-width,
initial-scale=1.0,
minimum-scale=1.0">
In your <head>, which will force the pages to render at the device's width (or individual browser's width on that device, if you have, say Opera+Chrome+Android+etc installed on an Android, which will all likely be the same viewport, anyway).
For most 10" tablets, the viewport is the resolution of the device.
For most phones, the viewport-width (in portrait) is 320px - 360px.
So even though the Galaxy S4 and Note 3 might be 1920x1080, they're really 640x360 when the viewport is enabled (where each CSS pixel has 9 [3x3] screen-pixels worth of "sub-pixel" anti-aliasing applied, and where fonts/images are rendered at the full-resolution of the screen-pixels [a 200x100 image in CSS width/height could actually be a 600x300 image]).
Instead of 3:1, "retina" iDevices have a 2:1 viewport DPPX (dot-per-pixel).
Other Androids/BBs/browsers have wonky, potentially-fractional DPPXs (so depending on Int-based DPPXs in equality tests should be avoided, too).
Then, you can test in JS, by using document.body.getBoundingClientRect().width, assuming that your body and layout are set appropriately in CSS.
If you aren't already doing this, then you probably have more to worry about in your responsive-design than whether an ad seems too big or too small.
In terms of UA-sniffing, it is occasionally valid.
That is, it's valid when you sniff the UA from your server-side language, against a DB of all-known UAs for phones/tablets, and then pre-compose an HTML page with baked-in CSS/JS, and pre-optimize images for that exact model...
However, that's not sniffing for specific sections of a UA string, that's searching every UA string for an exact match, and building to the specs of that device.
The reasoning is simple here:
How do you differentiate, in a UA, between all Android phones, all Android tablets and all other "miscellaneous" devices which run on the Android platform, when there is no standard way of defining every facet of the device+browser?
You might know the difference between an iPhone and an iPad, but how do you know the difference between Chrome on a generic 6" Taiwanese cell-phone and a generic 7" Taiwanese tablet?
The one instance of UA-sniffing that I can think of being valid is the .toDataURL() method of canvas in Android 2.2, which was technically added (you can detect it), but was never implemented (it just returns blank data, because the function was never actually written).
EDIT
SASS example, assuming Meta-Viewport is set properly
// my-widget.scss
// assuming a 1920x1080 phone (Samsung S4, Note 3 / Google Nexus 5 / HTC One)
// assuming 1920x1080 is max tablet size (with portrait width 1080)
// assuming that larger than 1080 is desktop
.my-widget {
// default experience
background-color : grey;
color : black;
font-size : 1rem;
// 1080px phone
#media screen and (max-width : 360px) {
font-size : 2rem;
background-color : white;
color : black;
}
// tablets up to 1080px, or phones in landscape-mode
// (or really-really big phones... none in North America, that I know of)
#media screen and (min-width : 361px) and (max-width : 1080px) {
background-color : black;
color : white;
}
}
Don't want to allow phones in landscape to move to a different layout, then increase it to 640px, or add an orientation-check to the #media rule.
Realistically, you shouldn't be targeting device-constraints. What you should be doing is targeting content-restraints.
Where does it make sense for your widgets to flow out into three or four columns, and where does it make sense (at what pixel/em-widths) to make everything break down into single-column mode, because your experience breaks otherwise.
But the point is that with the viewport set, you can now serve the super-small experience to the Samsung Galaxy Gear, the Nintendo 3DS, etc... a small experience to phones, a medium experience to iPads and 7"/8" tablets, a larger-medium experience to full-sized tablets, a desktop/TV experience, and a stupid-huge experience to people with multiple-monitors, or the Nexus 10, or 4k TVs, et cetera.
And it all comes at no extra sniffing...
Just a little planning, and some media queries.
You can add as many or as few breakpoints as you like.
Heck, knowing that the iPhone is 320px, you could serve an experience specifically to things sized exactly like iPhones, and then serve generic mobile from 321 up to 480 (or 640), or just make one responsive-grid flow all the way from 320px to 768px (iPad width), and have that be your "small", and serve everything larger as desktop...
Sky is the limit.
You just need to know what breakpoints you care about.

Is there a way to make page layout fit perfectly at 100% zoom but also respect greater zoom factors?

There are several ways to layout web pages so they fit the browser viewport (DOM window). When I say "fit" I include changing the size of the fonts used and changing the width and perhaps heights of DIVs, IMGs, and other rendered elements, as well as allowing "fluid" movements of elements. The goal is to make the page look "nice" on all display devices, from tiny phones to big desktop screens. These layout ways include using CSS em and % sizes, wrapping of text and elements, and JavaScript run by the onload and onresize events. Layout fitting can be made to work almost perfectly, cross-browser, but a sophisticated result may be insensitive to browser zooming, since zooming changes the window width magically, which means without any browser-independent, reliable way to detect the zoom (DOM and CSS standards ignore browser zooming). There is no way to detect the difference between a small window width due to a small device screen versus a small window width due to a large zoom factor. We want to handle these two cases differently, since vision-impaired users need the zoom factor to be honored.
Has anyone succeeded in fitting layout really well (including changing font sizes) in a way that respects zooming? For example, if the user visits the page with a zoom of 200%, initially only the upper left quarter of the page should be shown (the rest being available by scrolling horizontally and vertically), while the same page would fit into the window perfectly for another user having their zoom set to 100%.
Indeed to have a fluid layout you will have to use % to determine the width instead of pixels.
And for fitting the screen use 100%
Just add the following metatag
<meta name="viewport" content="width=device-width,
initial-scale=1.0,
maximum-scale=1.0,
user-scalable=0">

Redirect to mobile page when width is too small

Since my website doesn't look good at all on a small screen, I want to create a JS function that redirects me to a mobile version of the page when width of the screen is smaller than or equal to 800px.
Here is the code for it:
if (screen.width <= 800) {
document.location ="index_mobile.html";
};
If the code works, then when I shrink down the browser window to 800px wide, the index_mobile.html should show up. But it is not showing up right now. Does anyone know what's going on?
http://jsfiddle.net/RZMmV/
Mobile browsers do not report or use the real device resolution because this would make basically all websites on the internet unusable.
What they do is creating a "virtual screen" that has a resolution that is closer to the resolution of a desktop PC and then will implement zooming on the page.
If you want to know the real device resolution you need to disable automatic scaling done on the device. For example for iOS and Android devices this can be done adding
<meta name="viewport"
content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
to the <head> section of your page. This informs the browser that the page has been designed for handling low-resolution devices and disables the virtual screen layer.
screen.width will return the width of the monitor, not the window, so you can't just shrink your browser window down to get a different value. To do that, you'll want to use window.outerWidth or something.

Android browser setting element size too small

I have a website using the meta tag <meta name="viewport" content="width=device-width, target-densityDpi=device-dpi">, Javascript that formats the css for body to screen width and height, and elements inside that have percentage-based widths.
On desktop, this works fine. On my Android phone and tablet's browsers, though, the content isn't scaling properly - everything is just a little too small, and double-tapping to zoom zooms in to the right size (while not displaying the entire page width). This happens both in portrait and landscape mode, and the zoom level appears to be identical, or at least similar.
I have an alert come up telling me what the javascript has formatted body width and height to, and it is always right, but the browser feels the need to load as though the size of the window was actually larger.
I understand there's some nonsense where browsers get confused between CSS pixels and real pixels, but I thought the meta tag there was supposed to fix all of that.
So how do I make the browser load the page to a real 100% screen size, and not some sort of ~125% size?
Add
user-scalable=no
to your viewport meta-tag, this (at least in my tests) forces the browser to display at the width specified instead of the user/browsers preference.

Categories