(that is, as the width decreases on desktop, the media query kicks in at 720px. On phones, this should only happen when it is in portrait mode - landscape should not have the media query applied)

The problem is: how to target devices separately from desktops.

Problem exists because: @media handheld is not supported

Additionally max-width effects everything, so it can't be used in conjunction with max-device-width AND portrait

Seems like I can only target either:

all devices bellow/between set widths

only devices (using a JavaScript shim to fix media queries) bellow/between set widths and orientation.

CANNOT treat devices and desktops separately.

Is there an existing JavaScript solution which would fulfill my needs?

note I am coding my CSS in LESS, the media queries are nested within.

Background

The site I am working on is responsive and uses a grid system. At 720px width (current testing width) column usage changes for smaller devices / resolutions. Upon testing, however, the site (full site at 720px width) was pleasantly readable in landscape, even on my small screen HTC Desire. As I am removing portions of the site for better usability with media queries, I thought why not have the site normally accessible in landscape.

Bellow 720px on a desktop without modifying element column spans sees a pretty crushed site. However, due to the smaller nature of a mobile device it doesn't appear so. However with the column span modifications, particular elements are simply out of proportion (such as the heading) when it comes to landscape on a phone (due to the much reduced height of the browser).

Simply put, changing the design purely on browser width doesn't carry across all devices equally, as I have managed to achieve on other sites.

Would work great, but android 2.2 and 2.3 (possibly others, not to mention other OS?) have issues with max-device-width not working.

@media screen and (max-width:720px) and (orientation:portrait) { }

Works on high res monitors (since height quickly becomes > width as you decrease width of the window) and phones, but wont work on smaller monitors, as the windows wont be portrait at 720px width (site keeps condensing past the limits I want).

5 Answers
5

I think the best method is, according to MDN (Mozilla Developer Network) using window.innerHeight documentation here and window.innerWidth documentation here where it measures the browsers width and height in pixals to determine the orientation.

+1 Although thought this would be an excellent starting point, it's better to use the Detect Mobile Browser JavaScript plugin, which is very lightweight and powerful. More on that in this SO Answer w/ jsFiddle DEMO. Cheers!
–
arttronicsDec 12 '12 at 8:04

Now how do I go from this point - being able to detect mobile devices with JavaScript - to being able to make a responsive site on desktops using media queries and max-width, and ignoring this rule when mobile portrait is detected? To make it more difficult, I'm coding in LESS, and the media queries are nested : D
–
PatrickDec 12 '12 at 9:00

1

@Patrick: to answer your question, I think the easiest would be to have the javascript upon detection add a class to the body tag (like mobPort), then have your media queries have what they do qualified in their css selector string with body:not(.mobPort) ...[your other selectors] so that when it detects that class, it does not apply the media query changes.
–
ScottSDec 12 '12 at 20:58

@Patrick: In addition to ScottS comment, you can see this SO Answer that shows how to select metatags based on conditional settings, and adapt that process using LESS.
–
arttronicsDec 12 '12 at 22:04

You should look into Modernizr. It includes feature detection/inference for virtually all useful modern browser features, notably including whether the device is touch-based via a simple Boolean check on Modernizr.touch. From there, you may be able to get away with testing for portrait/landscape by comparing document.width to document.height, something like:

For completeness, this is to explain how to use CSS selectors to qualify the use of media queries in the context of nested LESS.

@enginefree's answer, and the following comments, explained how to check for a mobile device, it's orientation and to manipulate an elements attributes based upon the result.

The following code illustrates how to use the LESS & and CSS3 :not selectors to display our media queries when the attribute or class we are looking for is not detected:

body {
/* this has the possible class or data attribute of 'mobile' */
/* this is not included in the nest as you can't climb at will */
/* the class or attribute (via our JavaScript) could be applied
to any element that sits above and outside of `#level-1` in
this example */
}
#level-1 {
#level-2 {
#level-3 {
#level-4 {
body:not(.mobile) & {
/* produces the following CSS */
/* body:not(.mobile) #level-1 #level-2 #level-3 #level-4 { } */
/* rules in this block will only be executed if body does not have a mobile class */
@media screen and (max-width:) {
}
}
body:not([data-device=mobile]) & {
/* produces the following CSS */
/* body:not([data-device="mobile"]) #level-1 #level-2 #level-3 #level-4 { } */
/* rules in this block will only be executed if body does not have a mobile data-device attribute */
@media screen and (max-width:) {
}
}
}
}
}
}

If the body element was part of this nest, you would end up with the following CSS, and this should explain why the element must exist out of the scope of the nest, as well as above it: