I'm having a problem detecting a retina iPad (and similar devices) using just screen.availWidth and window.devicePixelRatio. The problem is that iPhones and iPads give the number of dips for screen.availWidth whereas android devices seem to report the number of physical pixels so I can't reliably do screen.availWidth / window.devicePixelRatio to calculate if the screen is of a tablet size.
Is there some other DOM property I can use to help me?
edit - To sum up in a way which hopefully makes clear that the question isn't a duplicate
How can I tell if screen.availWidth reports a value that has already been adjusted to take account of window.devicePixelRatio
That should help
var retina = (window.retina || window.devicePixelRatio > 1);
UPDATE
Retina.isRetina = function(){
var mediaQuery = "(-webkit-min-device-pixel-ratio: 1.5),\
(min--moz-device-pixel-ratio: 1.5),\
(-o-min-device-pixel-ratio: 3/2),\
(min-resolution: 1.5dppx)";
if (root.devicePixelRatio > 1)
return true;
if (root.matchMedia && root.matchMedia(mediaQuery).matches)
return true;
return false;
};
I haven't tested this, but here's an approach I think might work. I'll do a jsbin for it when I get time.
Because all devices (to the best of my knowledge) adjust for devicePixelRatio before passing the value to CSS media queries we can (in slightly pseudo code)
measure window.devicePixelRatio and screen.availWidth
Write a style tag to the head which includes a media query something like the following
#my-test-el {
display: none;
visibility: visible;
}
#media screen and (min-device-width:screen.availWidth) {
#my-test-el {
visibility: hidden;
}
}
Append <div id="my-test-el"> to the page
Read off the style.visibility attribute. If it equals hidden then the css value is the same value as screen.availWidth => screen.availWidth has been preadjusted for dpr.
edit It works! http://jsbin.com/IzEYuCI/3/edit. I'll put together a modernizr plugin too
edit And here's the pull request to get it in Modernizr - https://github.com/Modernizr/Modernizr/pull/1139. please upvote if you'd find it useful
This Modernizr plugin may help : Modernizr Retina : HiDPI Test
Note: Requires Modernizr's Media Queries feature
Related
How do I turn Javascript off when my page is viewed on mobiles?
I need a sort of media query that will disable all javascript on a page when viewed on a specific device.
So far I have this but do not know how to actually disable all javascript
if(screen.width < 480) {
// do any 480 width stuff here, or simply do nothing
return;
} else {
// do all your cool stuff here for larger screens
}
Thanks
You could use matchMedia.js (found at https://github.com/paulirish/matchMedia.js) and check if the screen is below a certain size.
Eg.
if (matchMedia('(max-width: 480px)')) {
// Run Code Here
}
You can check the
navigator.userAgent
property with Javascript. This will show the used browser and you can determine if its mobile or not.
Documentation:
userAgent Docs
You can do it also width the viewport width of your users browser in pure Javascript:
var w = document.documentElement.clientWidth;
I'm, setting up the mobile side of a website at the moment, and I need custom CSS and Javascript for mobile, so in the CSS I have rules using #media screen and (max-width: 500px) { and in Javascript I was going to use if ($(window).width() < 500.
However, if I resize my browser to the exact pixel the mobile CSS starts being used and I console.log($(window).width()); I get 485.
Is this normal behaviour or am I doing something wrong?
Update:
Using this, the values seem to be in sync, only tested in firefox though at the moment.
var scrollBarWidth = false;
function mobileRules() {
if (!scrollBarWidth) {
var widthWithScrollBars = $(window).width();
$('body').css('overflow', 'hidden');
var widthNoScrollBars = $(window).width();
$('body').css('overflow', 'scroll');
scrollBarWidth = widthNoScrollBars - widthWithScrollBars;
console.log('Width: '+widthWithScrollBars+'. Without: '+widthNoScrollBars+'. Scroll: '+scrollBarWidth);
}
console.log($(window).width()+scrollBarWidth+' vs '+globals.mobile_width);
if ($(window).width()+scrollBarWidth < globals.mobile_width) {
console.log('Running mobile rules in jQuery');
}
}
In firefox, media queries consider the width of the scrollbar to be inside the screen width.
This is what gives you the 15px wider screen width.
In webkit based browsers they don't.
If you're interested in why this thing happens, I'll quote this comment of this article :
A problem with Webkit browsers (that aren't following spec) is that the browser can encounter an infinite loop condition caused by media queries, which leads to a browser crash.
For example: >500px overflow-y: scroll, <500px overflow-y: hidden. Size your browser to 505px window width. Since the scroll bar subtracts 15 or so pixels from the width used by the media query, the media query flips you to < 500, but as soon as you hit <500 the scrollbar goes away, and the media query flips you to >500, and then the fun starts because now you have a scroll bar again and you're <500px and you get that style with no scroll bar... Rinse and repeat until the browser finally dies.
Now, write some javascript to calculate the media query max widths, and you have a page that will crash Chrome/Safari as soon as you load it.
My guess is that the spec was written the way it was to prevent this condition. Firefox & Opera are following spec, it's not really their fault you don't agree with spec.
I have a jquery funciton which sticks the navbar to the top of the webpage, but I only want this feature in desktop and tablet mode (not in phone mode). How do I de-activate this function?
$(document).scroll(function(){
var elem = $('.navbar');
if (!elem.attr('data-top')) {
if (elem.hasClass('navbar-fixed-top'))
return;
var offset = elem.offset()
elem.attr('data-top', offset.top);
}
if (elem.attr('data-top') <= $(this).scrollTop() )
elem.addClass('navbar-fixed-top');
else
elem.removeClass('navbar-fixed-top');
});
Use CSS media queries to manipulate the nav bar. Browser/OS detection shouldn't factor into styling, just resolution and media type.
What is the syntax for a CSS media query that applies to more than one property (AND operator)?
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries
Based on your question, it seems like the real concern here is saving screen real estate on a mobile device. So as most of the other users have pointed out, you can rely on using media queries here instead. In order to make sure the listener isn't even attached in case of small screens, you can use Modernizr.mq to test a media query and use the returned value:
if( Modernizr.mq('only screen and (min-height: 640px)') ) {
// Case specific code here, only executed if screen height is > 640px
}
This is assuming you're willing to add Modernizr or are already using it. If you don't have it already included and only plan on using this single test, you can download a custom build(2kB) from modernizr.com which only includes the media query test.
Check this out -- It maybe what you're looking for they're Open source mobile phone detection
http://detectmobilebrowsers.com/
I'm working on a web application for tablets(for android and ios) and I'm facing a problem which is
giving me trouble for 2 days already.
The problem is that on android when you are in portrait mode and for example you focus an input field so the soft keyboard pops up the css media query orientation changes to landscape.
I already have read this question : CSS Media Query - Soft-keyboard breaks css orientation rules - alternative solution? and came up with this :
var is_keyboard = false;
var is_landscape = false;
var initial_screen_size = window.innerHeight;
window.addEventListener("resize", function() {
is_keyboard = (window.innerHeight < initial_screen_size);
is_landscape = (screen.height < screen.width);
updateViews();
}, false);
function updateViews()
{
if(!is_landscape)
{
if(is_keyboard)
{
$("html").removeClass("landscape portrait");
$("html").addClass("portrait");
}
}
}
However this doesn't work for some reason.
Is there anyway to change the orientation to portrait mode so the css media query thinks
we are in portrait mode ? I prefer not the use max-width etc because I need to support multiple screen sizes.
Thanks in advance.
After some searching I came up with this :
#media screen and (min-aspect-ratio: 13/9){ } // landscape
#media screen and (max-aspect-ratio: 13/9){ } // portrait
instead of
#media (orientation : landscape){ }
#media (orientation : portrait){ }
So if you are in the same boat as me I would advise you to just go
with this, so you spare yourself the headache.
There is this good article to solve this problem.
But sometimes 13/9 is not enough.
#media screen and (min-aspect-ratio: 14/9){ } // landscape
Becareful, if you increase it to 16/9, iphone5 don't recognize the landscape.
Separate from min and max "-aspect-ratio" are min and max "-device-aspect-ratio" which are the parameters for the device rather than the screen.
#media only screen and (max-device-aspect-ratio:1/1){
section{background:purple;}
:root{--devmul:1;}
}
#media only screen and (min-device-aspect-ratio:1/1){
section{background:orange;}
:root{--devmul:0.5;}
}
Mozilla et al say the parameter is deprecated but they leave no note as to what it has been deprecated by. Im operating by the assumption that the deprecation is that the parameter is not supported on all devices (like desktop browsers) but is generally available on devices which have an orientation.
The above snippet operated in the context of assumption that the user is on a desktop which is then corrected according to "device-aspect-ratio" and the general aspect ratio. Havent had the opportunity to test my theory out on portrait based desktop devices but this seems to work on all the mobile devices I have.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
$(window).width() not working in IE9
I'm trying to do some DOM manipulation for responsive web design. In IE this is not working.
var w = $(document).width();
if (w > 940) {
console.log("If test");
} else {
console.log("Else test");
If I use window.width, it works in IE but stop working in other browsers. Is there a cross browser way for that?
var maskWidth = window.innerWidth;
var maskHeight = window.innerHeight;
As per, $(window).width() not working in IE9
Responsive designs should be done in CSS with media queries:
#media all and (max-width:940px) {
/* some style rules that should be put in place
if the window is smaller than 940px wide */
}
There is an inherent problem with your approach, and that is that "responsive" refers to the design responding to a change in size. With what you are doing here, you only get a detection when the browser loads.
Say, for example, you are using an iPhone to view this site and you turn the phone 45 degrees to landscape instead of portrait. Essentially, your width just changed but your width() didn't.
There are a couple of options I would recommend looking at if you need to use javascript for your DOM manipulation and can't accomplish it with pure CSS (which is generally the best way to go):
Check out the proposed matchMedia() method by Rob Tarr http://seesparkbox.com/foundry/responsive_web_design_and_javascript
Use http://modernizr.com/ or some other library that has already solved this problem for you.