How to fix iOS Viewport Bug(s)? - ios

Imagine the following setup:
<meta name="viewport" content="user-scalable=yes, width=640" />
Default CSS:
body { width: 100%; }
CSS change on some element (let's call it button-X) click:
body {
margin: 0 0 0 -webkit-calc(100% - 100px);
min-width: 640px;
overflow-x: hidden;
}
What does this do in desktop browser?
It shifts entire body almost 100% to the right. Horizontal scrollbar doesn't appear. You only see left part (100px) of the body positioned to the very right of your screen.
What does this do in iPhone 4S iOS 6.0.1?
There are two behaviors actually:
INCORRECT: If you just run Safari and click button-X it will start displaying your website at like 1200px instead of 640px.... shifted body will make entire viewport have 630px of blank space + body width = ~1200px. Even if body has position: absolute; or position: fixed; which in theory should allow positioning elements outside viewport but it doesn't. iOS makes viewport so large that your elements that are supposed to be off the screen are on the screen.
CORRECT: I wouldn't ask this question because maybe that's how it works and it can't be changed BUT there is fix for that so I assume it's a bug of iOS. If I run Safari and I tap it with 2 fingers and move them together (like to zoom out) and then click button-X it works perfectly. This action of tapping with two fingers doesn't change anything to viewport. Since viewport is set to 640px it will remain 640px after releasing fingers so literary nothing changes... but it starts working perfectly fine after this simple action.
The question is - how to perform this action (2) programmatically? I've tried:
jQuery(window).trigger('resize');
-webkit-transform-origin: 0px 0px; -webkit-transform: scale3d(1,1,1); zoom: 1;
How do I reset the scale/zoom of a web app on an orientation change on the iPhone?
Interesting: it will make viewport ~1200px even if you set user-scalable: no
This didn't change anything. Basically I want absolutely positioned elements (or with overflow: hidden;) to be off the viewport like in desktop browsers.

Have you tried initial-scale=1, maximum-scale=1, user-scalable=no? Also, I think you are trying to fix it backwards. What is exactly the thing you want to do? Not the behaviour of the viewport or DOM elements, but the result website/webapp.
Anyway - in general, viewport is body. It's weird to make the body wider than the viewport and expect the body to clip itself. Try setting the body at a fixed width (not minimum, because this way it can get as much wide as it wants), and putting a div container inside the body, and apply your margin CSS change to the div, not the body - body should have the width set and overflow-x:hidden.

Related

iOS Safari virtual keyboard shifts html tag outside the screen

We are developing a slightly bigger solution using angular - and currently cordova for our native builds (we will change that soon).
In our App we have multiple Input fields. When focused the complete site automatically gets shiftet towards top to display the input field properly - that's the standard behavior of iOS/Safari as far as i am aware of.
Our Problem is that, sometimes, when we enter the input field the page gets shifted a bit too much towards the top. (the amount of shifting is completely random but always relatively small)
So if we leave the input the complete html-tag is slightly offset and there is a space between the bottom of the display and the html-tag itself.
The html-tag itself keeps it size, so its leaving the screen on the top-end.
I have added a red border to the html-tag to hopefully make it more clear:
how it should look (red border at the top is visible)
shiftet html bottom 1 (red border at the top is not visible anymore)
shiftet html bottom 2 (red border at the top is not visible anymore)
Basic html structure
<html>
<head>
...
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no">
...
</head>
<body>
<app-root>
<home-component>...</home-component>
</app-root>
</body>
</html>
css:
html {
height: 100%;
float: left;
display: block;
border: 2px solid red;
}
body, app-root {
display: block;
}
home-component {
display: flex;
flex-direction: column;
height: 100%;
height: -webkit-fill-available;
}
If I add a margin-top to the HTML tag, I can slide it down far enough. If I set the margin-top to a negative number, the HTML tag will align itself correctly again.
I have tried several things now including absolut positioning, playing around with vh, px, %, etc. or the reworking of the whole html/css structure. Also i checked the meta viewport (see html snippet).
Perhaps I should add that we don't move or animate any elements via js or css and that scrolling is only allowed in certain components in our solution
On the android devices or as a pwa the app works flawless. So i think it must have something todo with the virtual keyboard of safari/ios.
This problem is driving me nuts ... i hope someone can help me or direct me into the right direction.
So this is my first question here on stackoverflow, so please dont tear me apart ;)

Mobile Safari: inertia scrolling on body AND minimal UI behavior?

This question requires some explaining, so please bear with me.
Contrary to popular belief, inertia scrolling (the very smooth 60fps scrolling) is not enabled on web pages in Mobile Safari by default. As it makes a world of difference in user experience, I have enabled it by dynamically applying this CSS to the HTML and BODY element of the page, after a Modernizr test for iOS specifically:
<style>
.touchscroll {
overflow: auto;
-webkit-overflow-scrolling: touch;
position:relative;
height:100%;
}
.touchscroll body {
height:100%;
overflow: auto;
-webkit-overflow-scrolling: touch;
position:relative;
}
</style>
The above basically makes the body element a scrollable element and by means of -webkit-overflow-scrolling: touch, one gets the smooth intertia scrolling effect on the entire page. Some more background on this solution can be found here (disclaimer: article by myself).
It works, so far, so good. The problem is that this solution effectively disables another highly desired behavior of Mobile Safari: normally, when scrolling down, it will make the address bar smaller, and hide the bottom bar of the browser entirely. They re-appear when scrolling back up.
Unfortunately, the above technique disables this for some reason. Yes, we've got super smooth scrolling, yet the browser bar is always large and the bottom bar permanently stays visible, both taking up valuable space.
My question therefore is, can I have both? I want the super smooth scrolling on the entire page, yet I also want the default hiding behavior of browser elements when scrolling.
An example of a site where I am using this is here:
http://www.jungledragon.com/
If you open that in Mobile Safari, you will see the smooth scrolling, yet not the hiding of browser elements when scrolling down.
I think you're setting both the <html> and the <body> element to scroll. You should apply these CSS rules to 1 element you want to be able to scroll.
So either the html or body, not both.

CSS scale transformation on iOS Safari zooms page out

I'm trying to have a snippet of text "zoom & fade in" once the page is loaded. To do so, I'm creating a div with the text inside and setting it to transform immediately:
.whatIwantZoomed {
opacity:0;
/* Vendor Prefixes here */
transform:scale(4,4);
/* Vendor Prefixes here */
transition:transform 1s, opacity 1s;
}
Now, when called from my Javascript function, an animated class is applied which reduces the scale to (1,1):
.whatIwantZoomed.animated {
opacity:1;
/* Vendor Prefixes here */
transform:scale(1,1);
}
Now, on mobile Safari (both iOS 7 & iOS 8), the effect actually does work. The problem is the scaled text is actually larger than the width of the viewport, causing it to 'resize' and zoom the page out. As the animation occurs, the page resizes back to how it should be.
What I'm trying to do here is remove this unwanted viewport width alteration. I've tried setting the body to have a property of overflow-x:hidden; to no avail, and I can't seem to get the viewport metatag to help me either.
Can anyone shed some light on a solution here? Thanks.
EDIT: Added a fiddle demonstrating this. Notice the scrollbars in the HTML frame? That's what I'm trying to prevent.
Try this
DEMO
div {
text-align:center;
background-color:red;
transform-origin: 50% 50%;
transform:perspective(1200) scale(1);
animation:animated 1s ease-in-out;
}
#keyframes animated{
from{transform:scale(10);opacity:0}
}
For anyone coming across this, it seems to be related to this bug
The root cause is things that are off screen incorrectly trigger safari (or wkwebview) to resize the viewport.
Add this to your viewport meta tag:
shrink-to-fit=no

iPad/iPhone issue with CSS Sprites, incorrect positioning

I've run into an issue with CSS sprites used for a sidebar widget in our site. On the iPad with iOS 7.1, the sprites are all pushed down too far.
I have tried several other suggestions with no noticeable changes:
Specifying a background-size to prevent scaling (not a scaling issue)
Using background-clip and -webkit-background-clip to clip to padding box
Setting the viewport to minimum-scale=1.0, maximum-scale=1.0, as well as initial scale, disabling user scaling, etc.
You can see the icons on the following website:
http://eugenedining.com/featured-restaurants/
You'll notice it is only a vertical alignment issue. The icons are all in the right place horizontally. When you click on an icon, the active state (white on orange) does not shift around, althouhg it is still cut off. It is not a sizing issue.
I think the <span> element is actuall being pushed down by something.
Any ideas?
Preview:
So I guess there is a mysterious padding / linebreak issue of some kind that appears inside the <a> and before the nested <span> element.
Switching the span to absolute positioning has fixed the issue, but I'm still clueless where the extra space comes from.
Luckily most of my structure is done to the <a> element, so this was pretty straightforward to implement.
.tag-list li.tag-item a {
position: relative;
}
.tag-list li.tag-item a span {
position: absolute;
top: 0px;
left: 0px;
}

Jquery Mobile phonegap vertical content limited to viewport on IOS

I have a fairly strange issue that I'm experiencing with jquery mobile / phonegap and IOS.
I've created a web app with html / css and so far it works exactly as expected on android, (The content scrolls vertically in the viewport) however on ios (my test platform is an iphone 4s), the page is limited vertically to the viewport. It scrolls just fine, but all content that sits below the viewport vertically get's cut off, IE the only content that will display is what I see in the upper half of the page, nothing below the viewport will display.
an excerpt from my css file:
html, body {
min-height:100%;
overflow-x:hidden;
background-attachment:fixed;
}
body {
-webkit-touch-callout: none;
-webkit-text-size-adjust: none;
-webkit-user-select: none;
-webkit-font-smoothing: antialiased;
-webkit-backface-visibility: hidden;
-webkit-overflow-scrolling: touch;
}
and my html page, in the head section:
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1 minimum-scale=1; user-scalable=no" />
Here's a couple screenshots of the problem in action:
As you can see from the screen shots, the gradient "should" fill the whole page (ie, expand with content), and it doesn't as there seems to be a hard cutoff at the viewport edge, so any more than a single page of content is not getting displayed. While it's not visible in these screenshots the vertical scrollbars are appearing as they should and the scrolling works fine, just no content is displayed "below the fold".
I am not using iScroll or any other scrolling scripts, just fyi.
I'm not sure if this is some sort of height issue, as I have a min-height:100%; set on the html and body of the page, or if it's some sort of width-device-width issue in the meta tag? I also do not believe I have any overflow-y:hidden set, as that would have limited the content on other platforms, and they work perfectly.
I feel like I must be missing something really basic, as I'm sure it's got to be some sort of css setting somewhere that's limiting the content to the viewport only, and an exhaustive google search could find no similar issues.
Check if your apps default orientation is set to portrait instead of landscape, or if it even supports the portrait orientation. It almost looks like its displaying the app as if its in landscape mode while its clearly in portrait. You can find the available orientation in the Target>General tab, or in the info.plist.
So I've fixed it, and the weird thing is, I'm not exactly sure what I did to fix the issue.
I moved the .ui-page selector from the jquery-mobile file to my own css file, removed the min-height from the html selector and killed the overflow-x from the html, body selectors and boom, it now appears to be working as intended. Wacky... but hey, a win is a win. :)

Resources