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.
Related
My Web application is meant to be used on desktop computers and also on computers that are connected to TV screens.
I would like to apply different styling in these two different cases, but simple media queries do not work here: TVs resolutions are even smaller than computer monitors, even though the screen is much bigger.
Is there any way to detect such a scenario and apply proper styling ?
there is a CSS media query to check if the client screen is a tv
#media tv
(instead of #media screen for a classic computer screen).
There is also #media projector.
Suggest to take a look at CSS Units, especially the ones beginning with v, which are relative to the viewport's size...
To my understanding (correct me if I am wrong) a modern Responsive website will change to fit the size and type of device you are using. Or this can be applied if the size of the window changes.
My question is why does my mobile phone display a Responsive site just like how a modern 1080p monitor would display it.
Essentially, my current monitor is running at 30" and is at a resolution of 768p. My phone also has a resolution of 768p.
Many responsive websites use media queries to display a CSS file based on the pixel width.
Wouldn't this be the same for both my monitor and phone?
MY QUESTION: How can I make a site responsive based on the screen size (in inches, etc) and not the screen resolution or number of pixels.
EDIT: My responsive design has 3 levels of CSS for different pixel widths (media-queries). When viewing on a monitor or smartphone, it displays the higher-most level (above 767p). How can I get my smartphone to display my lowest-level CSS (below 480p) even though it actually has more pixels.
I recently created a website using similar tech http://www.super-rod.tv/
It targets on both PC and mobile devices and will response to dynamic browser width resizing.
I used media query with max-width listing from higher-most to lower. For 1080P screens it has the best full screen display and for larger ones like 4K screen it will be centered with a texture background, on lower res like 768P it uses a smaller set of images and also be centered just like on a 4K screen.
If you are only targeting mobile devices, you can use device-width instead see ref here width versus device-width
To force using lowest CSS set you can either by using the max-width of 1000px (I don't think those who are still using 800x600 on PC would be your target?), this would pass out all desktops, or you can use browser UA to tell (defining for all IE,Safari,FF,Chrome,Opera etc., and the rest are mobiles).
I'd like to categorize devices by screen width in client-side JavaScript code
All devices fitting to one hand (7" less) to mobile category
Treat other devices as desktop devices
Fallback: Treat devices which do not support necessary APIs as mobile devices
Question
Which related JavaScript and CSS APIs I could use to detect the screen physical dimensions? Please note that these APIs do not need to be necessarily supported in older browsers, as there is safe fallback. Also, I don't care about legacy desktop browsers either.
Firefox support is optional - if they have compatible APIs already.
Please note that this is about physical dimensions, not pixel dimensions.
There's no direct way to get the screen size in inches, but there are workarounds that use screen density to find the device size. It's not perfect, but you don't really need to know the exact size to 5 significant figures. Also, it is normally better to simply use pixel values, IMO.
HTML
Make a test div, and then see the number of pixels displayed to get the pixel density, then use that in your calculations. This should work, assuming that your browser/OS are configured properly (it didn't work in the this question but it was within half an inch on my computer).
EDIT: This is 100% wrong. The inch/cm measurements in CSS aren't based on an actual physical measurement. They're based on an exact conversion (1 inch = 96 px, 1 cm = 37.8 px). My apologies.
CSS
The best way to detect physical screen size is to use CSS media queries. The min-resolution and max-resolution queries can be used to get the resolution in either dpi or dpcm:
#media (min-resolution: 300dpi){
// styles
}
Combining it with the min-device-width and max-device-width queries, you get something like:
#media (resolution: 326dpi) and (device-width: 640) and (device-height: 960){
// iPhone
}
The problem is that if you want to target 7 inch devices, you'd have to have many resolutions and corresponding widths that go together, which could get complicated.
For more information:
MDN- CSS Media Queries
MDN- Resolution
"Mobifying" Guide
High DPI Images for Variable Pixel Densities (Somewhat Related)
Javascript
You can use window.devicePixelRatio to determine the screen density. From Android's WebView Reference:
The window.devicePixelRatio DOM property. The value of this property specifies the default scaling factor used for the current device. For example, if the value of window.devicePixelRatio is "1.0", then the device is considered a medium density (mdpi) device and default scaling is not applied to the web page; if the value is "1.5", then the device is considered a high density device (hdpi) and the page content is scaled 1.5x; if the value is "0.75", then the device is considered a low density device (ldpi) and the content is scaled 0.75x.
Then using this, you calculate the physical size by dividing this by the total number of pixels, which can be calculated with window.screen.width and window.screen.height (Don't use window.screen.availHeight or window.screen.availWidth because these only detect the available height).
For more information:
Android Webview Reference
MDN - Screen.width
MDN - Screen.height
devicePixelRatio Explanation
better to use CSS
#media screen and (max-width: 672px){
//your code for mobile category
}
#media screen and (min-width: 672px){
//your code for desktop category
}
how to detect, in a cross-browser compatible way, the pixel density of the device visiting a webpage so that one can either serve standard or highres images without forcing doubled images to any device?
Is there any javascript library that automates this?
Why setting for Retina
iPhone 4s, iPhone 5, iPad3, iPad4, Macbook 15", Macbook 13" all use Retina display.
Android also support high resolution display, as well as Windows 8(Lumia 920) as mentioned by #JamWaffles.
Adding high resolution support is good for user experience but it definitely add load for developer, as well as bandwidth for mobile. Somebody don't suggest doing that.(Peter-Paul Koch, see the bottom "further reading")
Breifing
There are two methods to implement this function. One is Javascript and the other is CSS. All current solutions are for Retina, but could extend to Android high resolution easily.
CSS solution is about Media Query and -webkit-min-device-pixel-ratio or -webkit-device-pixel-ratio
Simple to use.
Apply to all browsers.
Disadvantage: Good for background. Harder for <img> tag
Javascript solution is about window.devicePixelRatio property.
Advantage: Javascript could manipulate image source. So, if you are going to serve direct image instead of background, better to use Javascript
Could not apply to all browsers but current support is good enough. See below for list.
Need a bit more setting.
CSS Solution
For normal images, say an icon
.sample-icon {
background-image: url("../images/sample-icon.png");
background-size: 36px 36px;
}
For Retina, add those below
#media only screen and (-webkit-min-device-pixel-ratio: 2), /* Webkit */
(min-resolution: 192dpi) /* Everyone else */ {
.sample-icon {
background-image: url("../images/sample-icon-highres.png");
background-size: 18px 18px;
}
You can use min-resolution: 2dppx to replace min-resolution: 192dpi, for those who don't want to remember numbers
Note the difference:
Two different icons, one normal, one high res. High res icon is double size than normal one.
The background size. The later is half. But you need test it in your real use.
Resource:
+ http://www.w3.org/blog/CSS/2012/06/14/unprefix-webkit-device-pixel-ratio/
+ http://view.jquerymobile.com/master/demos/widgets/buttons/#CustomIcons
Javascript Solution
Use window.devicePixelRatio property to detect resolution.
if (window.devicePixelRatio >= 2) {
alert("This is a Retina screen");
//Do something to manipulate image url attribute
//for example add `#2x-` before all image urls
}
Browser Support
Safari, Android WebKit, Chrome 22+ and on Android, Opera Mobile, BlackBerry WebKit, QQ, Palm WebKit,
Ref: http://www.quirksmode.org/blog/archives/2012/06/devicepixelrati.html
For Android
Android device use 1.5 as high resolution instead of 2 in Retina.
http://developer.android.com/guide/webapps/targeting.html --#Targeting Device Density with CSS, #Targeting Device Density with JavaScript
Further Good Reading
http://www.quirksmode.org/blog/archives/2012/07/more_about_devi.html
"I’m not a big fan of serving special retina images because it makes the web too heavy — especially over a mobile connection. Nonetheless people will do it." -- Peter-Paul Koch
Update 2013-04-18 Update jQuery mobile link
I found this:
var retina = window.devicePixelRatio > 1;
this should make retina return true, which you could use an if function to serve the right images.
Source: http://briancray.com/posts/detect-retina-displays-with-javascript
-InfiniDaZa
You need to be aware of network capabilities, responsive images and resource loading.
So far the javascript solutions are not quiet there as they generally require both resources (images) to be downloaded before the image swap.
Your best bet is background css media queries unless you go with a full solution like this:
http://adaptive-images.com
explained here: https://vimeo.com/38947881
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.