Mobile Website - Viewport depending on device-width - ios

I have a mobile website and a little problem with the Viewport meta tag in the -Part.
My code:
<meta id="testViewport" name="viewport" content="width=640">
It is working fine on an iPhone 4s but on the iPad 2, it doesn't work properly. I want the viewport to be set as the width of the users hardware. Is there a way to achieve it or do I have to read out the model type and set the Viewport with a switch or if code?
Thanks in advance.
Niels
edit:
Here's my CSS. What I want to achieve: let the site be displayed in the device-width. but if the display-size is smaller than 640px, then it should change the viewport to 640px. Not working on iOS 7.0, Safari:
#viewport {
width: device-width;
}
#media screen and (max-device-width: 640px) {
#viewport {
width: 640px;
}
}
edit#2:
Fixed it using JS in the of the index.html:
<meta id="viewport" name="viewport" content="width=device-width" />
<script>
if (window.innerWidth < 640){
var vp = document.getElementById('viewport');
vp.setAttribute('content', 'width=640');
}
</script>

Instead of setting content="width=640" try this one <meta name="viewport" content="width=device-width">
UPDATE:
To serve high-res images / change zooming for retina devices with your css you could use something like this:
#media
(-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {
/* Retina-specific stuff here */
}

Related

iPhone4/4S vs other media queries

I'm trying to get a media query for smaller devices only, in particular iPhone4 vs iPhone5 and larger. I haven't even started android. I tried the media queries I found here but I'm not having any luck.
Here's a simple test.
<!DOCTYPE html>
<html>
<head>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0, maximum-scale=1, user-scalable=no, minimal-ui">
<meta name="format-detection" content="telephone=no" />
<style>
body { background-color: blue; }
/* ----------- iPhone 4 and 4S ----------- */
/* Portrait and Landscape */
#media only screen
and (min-device-width: 320px)
and (max-device-width: 480px)
and (-webkit-min-device-pixel-ratio: 2) {
body { background-color: red; }
}
</style>
</head>
<body>
Testing
</body>
</html>
I expected it to be red only on iPhone4/4S and blue everywhere else but instead it's red on iPhone4/4S/5/5s/6/6Plus. It's blue on iPadAir, iPad Retina, and Desktop.
I tried adding the iPhone5/5s queries from the same page so I have both the iPhone4/4s queries and the iPhone5/5s queries. In this case I get green on 4/4s/5/5s/6/6Plus whereas supposedly I'm supposed to get red on 4/4s, green on 5/5s and blue everywhere else.
/* ----------- iPhone 5 and 5S ----------- */
/* Portrait and Landscape */
#media only screen
and (min-device-width: 320px)
and (max-device-width: 568px)
and (-webkit-min-device-pixel-ratio: 2) {
body { background-color: green; }
}
Some other things I tried. I got rid of all the meta tags. No change. I don't really care about the min device pixel ratio. All I care about is if the screen is too small vs not too small. Big enough is iPhone5/5s. Anything smaller I need to do special stuff.
How do I get it to be red only on iPhone4? (or on smaller than iPhone5/5s)
NOTE: I'm trying to avoid settings things for iPhone4 and then resetting them for anything larger because I have about 20 settings I need to change for small screens. In other words, 20 settings are the default and only for iPhone4 sized screens do I need to change those settings. I don't want to have to set them 3 times if possible.
In other words I want this
default css
iPhone4 {
a few overrides
}
not this
default css
iPhone4 {
a few overrides
}
notIPhone4 {
try to undo overrides // :(
}
You can use device-aspect-ratio which is another great features of media query:
body { background-color: blue; }
#media screen and (device-aspect-ratio: 2/3) {
body { background-color: red; }
}
Here is more device-aspect-ratio that I got from here:
iPhone < 5: #media screen and (device-aspect-ratio: 2/3) {}
iPhone 5: #media screen and (device-aspect-ratio: 40/71) {}
iPhone 6: #media screen and (device-aspect-ratio: 667/375) {}
iPhone 6 Plus: #media screen and (device-aspect-ratio: 16/9) {}
Also you can be really specific if you want to target one model only, for instance for iPhone 6 Plus I use following which I got from here:
#media only screen
and (min-device-width : 414px)
and (max-device-width : 736px)
and (device-width : 414px)
and (device-height : 736px)
and (orientation : portrait)
and (-webkit-min-device-pixel-ratio : 3)
and (-webkit-device-pixel-ratio : 3)
{ ... }

iPad portrait viewport issue

My test site is here: one-story-beta.herokuapp.com
I am having an issue with the viewport in portrait mode, where the content is not scaling down correctly. It is fine in landscape view. This was my original viewport:
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
And then I tried:
<meta name="viewport" content="initial-scale = 1,user-scalable=no,maximum-scale=1.0">
But neither seemed to fix the problem. I've also tried to set a media query for portrait mode, where I set the body to be 768px. Something like this:
/* iPads (portrait) ----------- */
#media only screen
and (min-device-width : 768px)
and (max-device-width : 1024px)
and (orientation : portrait) {
body {
max-width: 768px;
}
header {
max-width: 768px;
}
}
But that didnt work either.
Am i missing something obvious here?

viewport on iPad strange behaviour

I'm pulling my hair out about this… I know it has been discussed in many threads, but I couldn't find a solution that works for me.
Different problems in iPad and iPhone
When I use this:
<meta name="viewport" content="width=device-width, maximum-scale=3.0,user-scalable=yes"/>
The page displays fine in landscape-mode (on iPhone and iPad)
The page is too wide in portrait-mode and can't be scaled down with pinching
Now (and this is kinda hilarious):
<meta name="viewport" content="width=device-height, maximum-scale=3.0,user-scalable=yes"/>
The difference is width=device-height (vs. device-width)
The page displays fine on the iPad in landscape- and portrait-mode
The page is too wide on portrait mode on the iPhone, works fine in landscape
When I use initial-scale=1.0 everything's messed up totally (I read that initial-scale shouldn't be used anyway?)
Does anybody have an explanation for this???
if You use this: this will fix when you load into Landscape and go to Portrait.
fixed width kills it i think, specialy if you have fixed PX min-width included.
// BUG orientation portrait/lanscape IOS //
if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) {
var viewportmeta = document.querySelector('meta[name="viewport"]');
if (viewportmeta) {
viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0';
document.addEventListener('orientationchange', function () {
viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1';
}, false);
}
}
also you can fix it with CSS , like this:
/* iPads (portrait) ----------- */
#media only screen
and (min-device-width : 768px)
and (max-device-width : 1024px)
and (orientation : portrait) {
/* Styles */
html {zoom:0.75;}
}
it will zoom to 0.75 in portrait mode only..
Can you first test this:
<meta name="viewport" content="height=device-height,width=device-width">

Phonegap: Keyboard changes window height in iOS 7

In iOS 6 everything works fine. The keyboard opens and moves the input into view. When the keyboard closes everything goes back where it should.
In iOS 7 the keyboard opens fine and the input remains in view. When the keyboard is closed the whole bottom half of the app is gone, though. I've tracked the issue down to the height of the window changing when the keyboard is opened, and not changing back when it's closed.
Right before the keyboard is opened the window height is 568 according to $(window).height() and after it's opened and after it's closed it is 828. The height of the document also changes accordingly.
I've attempted preventing the window from resizing with:
$(window).resize(function(e) {
e.preventDefault();
e.stopPropagation();
window.resizeTo(320,480);
return false;
});
I've also attempted to set the size back after the keyboard closes with no success.
I'm using phonegap 2.7 and have KeyboardShrinksView set to true.
I was seeing this too. After the height changes, some of our absolute positioned elements disappear off the bottom of the screen.
I found that with KeyBoardShrinksView = false in ios7, window.height stayed constant. This was the opposite of ios6 though, so a bit of a catch 22.
Not sure if there's a better way of handling this in Phonegap, but I put this in CDVViewController.m, created to config.xml files for ios < v7 and ios > v6, and my app works the way I want. Seemed a bit hacky, but not too disruptive of the rest of my code.
// read from config.xml in the app bundle
NSString* path = [[NSBundle mainBundle] pathForResource:#"config" ofType:#"xml"];
if (IsAtLeastiOSVersion(#"7.0")) {
path = [[NSBundle mainBundle] pathForResource:#"config_ios7" ofType:#"xml"];
}
(I also tried an app preference plugin at https://github.com/phonegap/phonegap-plugins/tree/master/iPhone/ApplicationPreferences but don't think this was designed for this kind of preference.)
After I upgraded my project to iOS with cordova 3.1 I start having similar problems for the input fields in where I did not have the code listed above. The keyboard pushes things up and the header and footer did not returned to their original positions. I have tested and that solve the problem (maybe not very elegantly but it is a workaround). I just put that code on my pageinit event.
/*************************************************************************************************
* FIX: to avoid the buggy header and footer to jump and stick not
* to the top/bottom of the page after an input or textfield lost focus and the keyboard dissapear *
*************************************************************************************************/
$('input, textarea')
.on('focus', function (e) {
$('header, footer').css('position', 'absolute');
})
.on('blur', function (e) {
$('header, footer').css('position', 'fixed');
//force page redraw to fix incorrectly positioned fixed elements
setTimeout( function() {
window.scrollTo( $.mobile.window.scrollLeft(), $.mobile.window.scrollTop() );
}, 20 );
});
add code into CDVViewController.m
for example it added into webViewDidFinishLoad function
CGRect newFrame = self.webView.bounds;
NSLog(#"%f" , newFrame.size.height);
NSString *JS = [NSString stringWithFormat:#"viewport = document.querySelector('meta[name=viewport]'); viewport.setAttribute('content', 'user-scalable=no, initial-scale=1.0, maximum-scale=0.5, minimum-scale=0.5, width=device-width, height=%d, target-densitydpi=device-dpi');", (int) newFrame.size.height*2 ];
[self.webView stringByEvaluatingJavaScriptFromString:JS];
this code change <meta name="viewport" content="..."> and set height of device
set your viewport meta tag to your html
<meta name="viewport" content="width=device-width,height=**yourheight**, initial-scale=1, maximum-scale=1, user-scalable=0" >
or
<meta name="viewport" content="width=device-width,height=**device-height**, initial-scale=1, maximum-scale=1, user-scalable=0" >
The Petrash's solution worked for me. But I had still problems supporting rotations on iPad.
So, in the same CDVViewController.m I've added this method:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
if (self.webView){
CGRect newFrame = self.webView.bounds;
//NSLog(#"%f" , newFrame.size.height);
NSString *JS = [NSString stringWithFormat:#"viewport = document.querySelector('meta[name=viewport]'); viewport.setAttribute('content', 'user-scalable=no, initial-scale=1.0, maximum-scale=1, minimum-scale=1, width=device-width, height=%d, target-densitydpi=device-dpi');", (int) newFrame.size.height*1 ];
[self.webView stringByEvaluatingJavaScriptFromString:JS];
}
}
and, to support the "non scale" behaviour, edited the Petrash's solution in this way:
CGRect newFrame = self.webView.bounds;
//NSLog(#"%f" , newFrame.size.height);
NSString *JS = [NSString stringWithFormat:#"viewport = document.querySelector('meta[name=viewport]'); viewport.setAttribute('content', 'user-scalable=no, initial-scale=1.0, maximum-scale=1, minimum-scale=1, width=device-width, height=%d, target-densitydpi=device-dpi');", (int) newFrame.size.height*1 ];
[self.webView stringByEvaluatingJavaScriptFromString:JS];
KeyboardShrinksView = false
This is hacky, but it works from 5.1 to 7.0.3. Tested on Cordova 3.0.
After hours of investigating I've managed to get it to work:
My div, that is pushed up and never get's down again,
had the css attribute
position:fixed;
I switched this to
position:absolute;
and everything worked!
The best way I found was to put everything into a div and fix its height via javascript.
Works on modern Versions of both iOS (5, 6, 7) and Android (4.2, ...).
<style>
body {
overflow-y: scroll;
overflow-x: hidden;
webkit-overflow-scrolling: touch;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
body > .viewport{
position: absolute;
top: 0;
left: 0;
right: 0;
}
</style>
<body>
<div class='viewport'>
<!-- Put everything here -->
</div>
</body>
<script type="text/javascript">
$("body > .viewport").height($(document).height());
// WARNING: if your app works in both landscape and portrait modus, then you should reset the height of the container when the app changes orientation
</script>
I had a similar issue that drove me nuts for days. Not sure if this will help anyone else, but this is what solved it for me: (note I'm using jquery finger library to listen to tap events):
$('body').delegate("#send_feedback_button","tap", function(event){
$('textarea').blur();
event.stopImmediatePropagation();
// do my stuff
});
For me calling blur on any textarea in the view was the trick. The stopImmediatePropagation got rid of some other funkiness.
I had the same problem and I managed to track it down to dynamic content.
I had initially an empty div that was filled with text using javascript.
When I pre filled the div with static text the problem was gone.
Looks like this div's height was not counted when resizing.

Styling media queries not working on Chrome iPad

So i have added some javascript to add a class to my body -
var deviceAgent = navigator.userAgent.toLowerCase();
var agentID = deviceAgent.match(/(ipad)/);
if (agentID) {
$("body").attr("id", "ipad");
return;
}
I have three media queries one for standard mobile and one for retina, some of the mobile styling seems to be showing on chrome on iPad the media query is below
#media only screen and (max-device-width: 480px) {
}
#media only screen and (max-device-width: 480px) and (-webkit-min-device-pixel-ratio: 2) {
}
And my third media query
/* iPads (portrait) ----------- */
#media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait) {
/* Styles */
}
But all the styles I put in either media query have no effect in Chrome on an ipad, it works perfectly on Safari on an iPad. Even the javascript which adding the class doesn't seem to be working, i've added
#ipad body {background-color:red!important;}
to the main css outside the media queries and nothing.
It's just chrome that isn't behaving. I have cleared the cache and browser data but still nothing.
Any ideas?

Resources