"Full web" mobile browsers and screen-size media queries based - iphone

I've been asked to retrofit an existing website with a mobile layout. The website was built on a Wordpress Twenty11 framework, so I decided to build the mobile layout using the existing media queries in that framework.
Now, my mobile layout looks great on any desktop browser dragged down to be less than 420px wide, but on iPhone & Android mobile browsers it just loads the full-width webpage anyhow. Full web experience, woot!
Client unhappy. Wants mobile design to show up on all iPhone browsers. So now I need to work out why the mobile browsers insist on showing the page at the full desktop width, ignoring the mobile CSS entirely.
Here's my media queries, down the bottom of the main style.css document:
#media (max-width: 800px) {
/* Design starts to get a little more fluid */
}
#media (max-width: 650px) {
/* Design gets quite a lot more fluid, and columns start dropping off the edge to below main content */
}
#media (max-width: 450px) {
/* Totally changed navigation for small viewports, main content takes up whole viewport */
}
All of these do what I want when I manually resize a browser window on a desktop machine. They also do what I want when I test them in next-to-useless iFrame-based "iPhone emulators". But all mobile devices so far tested stubbornly show the full-width layout, zoomed really far out and unreadable.
Is there something I should be adding to those media queries to MAKE the mobile browsers display the mobile CSS? Or should I be going with a different strategy altogether, such as user-agent detection or similar?
EDITED TO ADD:
Something like this line in header.php, I am guessing:
<meta name="viewport" content="width=960,
maximum-scale=1.0">
should in fact be
<meta name="viewport" content="width=device-width,
maximum-scale=1.0">
right?

You should add min-width parameters to your media queries because at the moment someone with a small screen will be getting rules from all three of your media queries since it's max width will be less than 800px.
#media (min-width: 651px AND max-width: 800px) {
...
}
#media (min-width: 451px AND max-width: 650px) {
...
}
#media (max-width: 450px) {
...
}
If you attempt to get too complex with media queries you'll run into tons of problems. Different browsers handle them differently making them less than ideal for a production environment.
A method that I like to use is to create a simple JS event handler for the window.resize event that only adds a class to the <html> element to specify what screen-break-point the user is at. Then in your CSS you just prefix rules with the breakpoint-classes:
$(window).on('resize', function () {
var w = $(this).width();
if (w > 1400) {
$('html').addClass('widescreen-viewport');
} else if (w > 1024) {
$('html').addClass('desktop-viewport');
} else if (w > 767) {
$('html').addClass('tablet-viewport');
} else {
$('html').addClass('mobile-viewport');
}
});
Sorry for the jQuery but this is a way I know works for sure.
Then your CSS would be something like:
#some-element {
/*default styles*/
}
.widescreen-viewport #some-element {
/*widescreen styles*/
}
.desktop-viewport #some-element {
/*desktop styles*/
}
.tablet-viewport #some-element {
/*tablet styles*/
}
.mobile-viewport #some-element {
/*mobile styles*/
}
This method will receive better browser support as it requires JS to be enabled but other than that, it'll work back to IE6/5.5 and other browsers from that time.

Related

How can I exclude certain text in mobile version of site?

I want to exclude some HTML (basically, text ) when my PHP site loads on a smartphone. What's the best way to code that?
Thanks.
if "on a smartphone" means "on a small device", you could use Media Query , just with CSS.
<style>
#media only screen and (max-device-width: 480px) {
.hide-mobile{
display:none;
}
}
</style>
And use it where you want to hide at small devices:
<div class="hide-mobile">
Hey, this text is not visible at small devices
</div>
If you want to go really simple, just use mediaqueries in your CSS to make the div be display:none; for mobile.
#media only screen
and (max-device-width: 480px) {
.containeroftextyouwanttohide{
display:none;
}
}
Then the div holding the text you want won't show up on mobile. There are probably other ways to do it, but this is the easiest and probably best.

Responsive CSS: Replicating how Facebook's chat panel disappears below a certain browser window width

Notice how facebook's right hand, ~200px-wide, chat panel/column disappears when you shrink your window below a certain width. (It then switches to a pull-out menu at the bottom)
I presume this is some sort of responsive CSS - can anyone offer any guidance on how I can achieve a similar effect with a similar right-hand panel on my own site?
Yes, it's using CSS Media Queries.
<style>
#media (min-width: 701px) {
//css for wide screen
}
#media (max-width: 700px) {
//css for narrow screen
}
</style>

iPhone is ignoring CSS media queries. Viewport tag present. Working in desktop

EDIT: This was a total rookie error on my part. I was editing a different fileset to the one I was testing. Sincere apologies to all who answered to help me out. I've upvoted all answers as I at least learned a little more on media queries from you all, but none provided the answer. Advice pls on what now to do with this ticket?
This is a busy topic on the site, but I haven't seen the solution for this problem.
The viewport tag is present. I'm using:
<meta name="viewport" content="width=device-width,initial-scale=1.0">
When I resize the browser window in Chrome, it works fine, and I can see it snapping to new breakpoints as they are reached, however iPhone Safari displays the top left of the site only, with no sign of picking up any queries.
The CSS Media query I'm using for iPhone portrait is:
#media (max-width: 321px) { }
I'm using Bootstrap and LESS, so my media queries are at the end of the styles.
Sorry I'm not in a position to share code on this. It's an odd one — I'm hoping someone can see if there's something I may be missing.
EDIT
Here's a very basic example which is working on my iPhone. I can rotate from portrait to landscape and the bg color will change - so there's nothing wrong with the media query I'm using:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<style type="text/css">
body
{
background: blue;
}
#media (max-width: 321px)
{
body
{
background: red;
}
}
</style>
</head>
<body>
Here is my content...
</body>
Edit
What solved this for me is a double ("or"-operated) media query, for either max-device-width or max-width. It's like David Rönnqvist's first suggestion, but it was only putting max-width, max-device-width BOTH in the media query that worked for me.
#media screen and (max-device-width:640px), screen and (max-width:640px) {
/* styles here */
}
BBTony, I hope this works for you.
I'm keeping the below because it is a fuller description of the problem than i've found anywhere else. I disliked my first solution (below the line) so much that I re-researched for the thousandth time - thanks to this post which gave me the above solution without the ridiculous !importants.
Edit: this also worked, but it's extremely inelegant: Putting "!important" on every line of the media query conditional CSS.
I was reluctant to propose that as an answer, but after going bonkers researching this for 3 days, it was the first thing that worked for me.
Full description of the problem: I had similar symptoms as BBTony. I had the viewport tag (and I had it above the stylesheets as recommended).
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
My media query, intended to catch any smallish device, was being ignored by an iPhone 3gs running iOS 5.1, but the same media query was being properly picked up by an iPhone 4s running iOS 6.
#media only screen and (max-device-width:640px) {
/* many styles here */
}
Very oddly, while most declarations within the media query were being ignored by the older iPhone, some of them were being respected. The newer iPhone 4s however respected all the CSS within the media query, as expected. On Safari desktop, the media queries all worked perfectly, snapping at both the breakpoints (there are 2).
I linted my CSS through several different linters, after reading here that CSS errors can cause mobile browsers to ignore media queries. After making certain that my CSS was compliant, and just for the hell of it, I put !important declarations after each and every line of CSS within the media query - like 80-100 !importants.
Presto.
I can't tell you how mad it made me that this even worked, and I'm curious why the old iphone would only respect the conditional with !important in this case.
I've previously used this for my site and it worked as iPhone specific media queries for me
#media only screen
and (max-device-width: 480px)
and (orientation:landscape) {
/* iPhone landscape */
}
#media only screen
and (max-device-width: 480px)
and (orientation:portrait) {
/* iPhone portrait */
}
Answers to other questions like this seem to suggest that 480px for the max-device-width is what you should go for in your media query.

Mobile CSS Won't Display

I'm trying to teach myself how to make a mobile version of a website, so I started off with something basic.
I have the following code
<body>
You are using...
<p class="mobile">
Mobile
</p>
<p class="desktop">
Desktop
</p>
</body>
with the CSS
#media screen and (max-width: 480px)
{
p.desktop {
display:none;
}
}
p.mobile {
display:none;
}
Basically, I want either "mobile" or "desktop" to display depending on which device you're using. When I navigate to the site on my desktop it says "desktop", so that seems fine.
But when I do so on my iPhone it still says desktop.
I have tried increasing the max-width to 640px which is the iPhone 4S' resolution. But I still have no luck. What am I doing wrong?
The default viewport on an iOS device is somewhere around 1000 pixels. You may notice when you pull up your test page that it doesn't look like it's a 320px wide - it's way zoomed out.
You need a viewport meta tag in your page head that sets the viewport width to that of the device:
<meta name="viewport" content="width=device-width">
Once in place, you'll find your #media query works nicely (although you need a p.mobile { display: block; } bit to make the "mobile" text show up).

How can you hide CSS from the iPhone, but not other browsers?

I know how to hide CSS from all browsers except the iPhone: see How do I apply a stylesheet just to the iPhone (and not IE), without browser sniffing?
But: how do I hide CSS from the iPhone, but not other browsers?
You could possibly use #media queries:
<link rel="stylesheet" href="noniPhoneStylesheet1.css" media="only screen and (min-device-width:490px)" />
Which would automatically exclude iPhone browsers from downloading that particular stylesheet (the iPhone's screen width being 480px); so putting any styles you want to hide from the iPhone into that stylesheet should work. Although, obviously, it'll also block that stylesheet from other devices that respect media-queries and have a screen width below 490px.
You can still do the conditional check, for iPhones append the iPhone CSS otherwise your normal CSS.
var agent=navigator.userAgent.toLowerCase();
var isIPhone = ((agent.indexOf('iphone')!=-1);
if (isIPhone)
document.createElement("style")... //iPhone CSS
else
document.createElement("style")... //normal CSS
Or a simple redirect to a page without the CSS, or use PHP to detect iPhones and deliver them a page without the style — something with a flow of:
if iPhone {
echo //page without CSS
else {
echo //page with CSS
}
I actually ended up going with a slightly different, and very ridiculous, solution that uses media queries and getComputedStyle to redirect to a mobile site if we’re on an iPhone-like device.
<style media="only screen and (max-device-width: 480px)">html{border-top-style:dashed;}</style>
<script>
if(window.location.search.indexOf("?m=t")==-1 && window.getComputedStyle) {
var mobile = false;
if(window.getComputedStyle(document.getElementsByTagName("html")[0],null).getPropertyValue("border-top-style")=="dashed") {
var mobile = true;
}
if(mobile) {
window.location.replace(window.location+"?m=t");
}
}
</script>
I’m sure I got the getComputedStyle idea on Stack Overflow, but I can’t remember where.