CSS iOS 7 iPad Safari Landscape 内高度/外高度布局问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19012135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS 7 iPad Safari Landscape innerHeight/outerHeight layout issue
提问by hisnameisjimmy
We're seeing issues with a web app that has a height of 100% on Safari in iOS 7. It appears that the window.innerHeight (672px) doesn't match window.outerHeight (692px), but only in landscape mode. What ends up happening is that in an app with 100% height on the body, you get 20px of extra space. This means that when a user swipes up on our app, the navigation elements get pulled behind the browser chrome. It also means that any absolutely positioned elements that are at the bottom of the screen end up being 20px off.
我们在 iOS 7 的 Safari 上看到高度为 100% 的 Web 应用程序的问题。看起来 window.innerHeight (672px) 与 window.outerHeight (692px) 不匹配,但仅在横向模式下。最终发生的事情是,在一个 100% 高度的应用程序中,你会得到 20 像素的额外空间。这意味着当用户在我们的应用程序上向上滑动时,导航元素会被拉到浏览器 chrome 后面。这也意味着屏幕底部的任何绝对定位的元素最终都会偏离 20 像素。
This issue was also outlined in this question here: IOS 7 - css - html height - 100% = 692px
这个问题在这里的问题中也有概述: IOS 7 - css - html height - 100% = 692px
And can be seen in this ambiguous screenshot:
并且可以在这个模棱两可的截图中看到:
What we're trying to do is hack around this so that until Apple fixes the bug, we don't have to worry about it.
我们试图做的是解决这个问题,这样在 Apple 修复错误之前,我们不必担心它。
One way of doing this is to absolutely position the body only in iOS 7, but this pretty much puts the extra 20px at the top of the page instead of the bottom:
这样做的一种方法是仅在 iOS 7 中绝对定位主体,但这几乎将额外的 20px 放置在页面顶部而不是底部:
body {
position: absolute;
bottom: 0;
height: 672px !important;
}
Any help with forcing outerHeight to match innerHeight, or hacking around it so that our users can't see this issue would be much appreciated.
任何强制outerHeight 匹配innerHeight 的帮助,或绕过它以便我们的用户看不到这个问题将不胜感激。
采纳答案by Samuel Moreno López
In my case, the solution was to change positioning to fixed:
就我而言,解决方案是将定位更改为固定:
@media (orientation:landscape) {
html.ipad.ios7 > body {
position: fixed;
bottom: 0;
width:100%;
height: 672px !important;
}
}
I also used a script to detect iPad with iOS 7:
我还使用了一个脚本来检测带有 iOS 7 的 iPad:
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i)) {
$('html').addClass('ipad ios7');
}
回答by mikeStone
Simple, cleaner CSS-Only solution:
简单、干净的 CSS-Only 解决方案:
html {
height: 100%;
position: fixed;
width: 100%;
}
iOS 7 seems to set the height correctly with this. Also there is no need for resize javascript events, etc. Since you are working with a full height app, it doesn't really matter if it is always position fixed.
iOS 7 似乎正确设置了高度。也不需要调整 javascript 事件的大小等。由于您正在使用全高应用程序,因此它是否始终位置固定并不重要。
回答by Andrea Tondo
Samuel's answer, as also stated by Terry Thorsen, is working great, but fails in case the webpage has been added to the iOS home.
Samuel 的回答,正如 Terry Thorsen 所说,效果很好,但如果网页已添加到 iOS 主页,则失败。
A more intuitive fix would be to check for window.navigator.standalone
var.
更直观的解决方法是检查window.navigator.standalone
var。
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && !window.navigator.standalone) {
$('html').addClass('ipad ios7');
}
This way it only applies when opened inside Safari, and not if launched from home.
这样,它仅适用于在 Safari 中打开时,而不是在家中启动时。
回答by Terry Thorsen
Samuel's answer is the best although it breaks if a user adds the page to their home screen (home screen pages don't exhibit the bug). Check the innerHeight before adding the class like so:
Samuel 的答案是最好的,尽管如果用户将页面添加到他们的主屏幕(主屏幕页面不显示错误),它会中断。在添加类之前检查innerHeight,如下所示:
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i)) {
if(window.innerHeight==672){
$('html').addClass('ipad ios7');
}
}
Note that the bug also does not exhibit under webview.
请注意,该错误也不会在 webview 下出现。
回答by czuendorf
I used this JavaScript solution for solving that problem:
我使用这个 JavaScript 解决方案来解决这个问题:
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && window.innerHeight != document.documentElement.clientHeight) {
var fixViewportHeight = function() {
document.documentElement.style.height = window.innerHeight + "px";
if (document.body.scrollTop !== 0) {
window.scrollTo(0, 0);
}
}.bind(this);
window.addEventListener("scroll", fixViewportHeight, false);
window.addEventListener("orientationchange", fixViewportHeight, false);
fixViewportHeight();
document.body.style.webkitTransform = "translate3d(0,0,0)";
}
回答by overmailed
A variant of Samuel's approach, but with position: -webkit-sticky set on html worked for me the best.
Samuel 方法的一种变体,但 position: -webkit-sticky set on html 对我来说效果最好。
@media (orientation:landscape) {
html.ipad.ios7 {
position: -webkit-sticky;
top: 0;
width: 100%;
height: 672px !important;
}
}
Notice 'top: 0', not 'bottom: 0', and target element is 'html', not 'body'
注意 'top: 0',不是 'bottom: 0',目标元素是 'html',不是 'body'
回答by Nick H247
The accepted answer doesn't cope when the favorites bar is showing. Here is am improved catch all fix:
当收藏夹栏显示时,接受的答案不适用。这是改进后的所有修复:
@media (orientation:landscape) {
html.ipad.ios7 > body {
position: fixed;
height: calc(100vh - 20px);
width:100%;
}
}
回答by user3432605
If I use this:
如果我使用这个:
if (navigator.userAgent.match(/iPad;.*CPU.*OS 7_\d/i) && !window.navigator.standalone) {
$('html').addClass('ipad ios7');
}
My Safari on Mac shows the same html classes... SO its not working correctly.
我在 Mac 上的 Safari 显示相同的 html 类......所以它不能正常工作。
I tried to combine a few things - that worked for me, so I can manage it in the browser and without Browser view.
我试图结合一些东西 - 对我有用,所以我可以在浏览器中管理它而没有浏览器视图。
jQuery
jQuery
if (navigator.userAgent.match(/iPad/i) && (window.orientation) ){
$('html').addClass('ipad ');
if (window.innerHeight != window.outerHeight ){
$('html').addClass('browser landscape');
}
else{
$('html').addClass('browser portrait');
}
}
CSS
CSS
@media (orientation:landscape) {
html.ipad.browser > body {
position: fixed;
height: 671px !important;
}
}
///// With this you are more flexible or other OS and Browsers
///// 有了这个,你可以更灵活或其他操作系统和浏览器
回答by ddlab
I came across this page for the same issue. There are a lot of useful answers here, and others not (for me).
我遇到这个页面同样的问题。这里有很多有用的答案,而其他答案则没有(对我而言)。
However, I found a solution, which works in my case, and works totally independent of which OS version and which bug now or in the past or future.
但是,我找到了一个解决方案,它适用于我的情况,并且完全独立于现在或过去或将来的操作系统版本和错误。
Explaination: Developping a web app (no native app) with several modules of fixed size in fullscreen, with class name "module"
说明:全屏开发具有多个固定大小模块的 Web 应用程序(非原生应用程序),类名为“模块”
.module {position:absolute; top:0; right:0; bottom:0; left:0;}
which contains a footer with class name "footer"
其中包含一个类名为“footer”的页脚
.module > .footer {position:absolute; right:0; bottom:0; left:0; height:90px;}
Nevermind, if I set the height of the footer later to another height, or even its height is set by its content, I can use this following code for correction:
没关系,如果我稍后将页脚的高度设置为另一个高度,甚至其高度由其内容设置,我可以使用以下代码进行更正:
function res_mod(){
$('.module').css('bottom', 0); // <-- need to be reset before calculation
var h = $('.module > .footer').height();
var w = window.innerHeight;
var o = $('.module > .footer').offset();
var d = Math.floor(( w - o.top - h )*( -1 ));
$('.module').css('bottom',d+'px'); // <--- this makes the correction
}
$(window).on('resize orientationchange', res_mod);
$(document).ready(function(){
res_mod();
});
Thanks to the skills of Matteo Spinelli I can still use iScroll with no problems, as its change events fortunately are fired after. If not, it would be necessary to recall the iScroll-init again after the correction.
感谢 Matteo Spinelli 的技能,我仍然可以毫无问题地使用 iScroll,因为幸运的是它的更改事件在之后被触发。如果不是,则需要在更正后再次调用 iScroll-init。
Hope this helps somebody
希望这可以帮助某人
回答by andraaspar
You need JavaScript to work around this bug. window.innerHeight
has the correct height. Here's the simplest solution I can think of:
您需要 JavaScript 来解决此错误。window.innerHeight
有正确的高度。这是我能想到的最简单的解决方案:
$(function() {
function fixHeightOnIOS7() {
var fixedHeight = Math.min(
$(window).height(), // This is smaller on Desktop
window.innerHeight || Infinity // This is smaller on iOS7
);
$('body').height(fixedHeight);
}
$(window).on('resize orientationchange', fixHeightOnIOS7);
fixHeightOnIOS7();
});
You'll also need to set position: fixed
on the <body>
.
您还需要position: fixed
在<body>
.
Here's a complete, working example:
这是一个完整的工作示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<title>iOS7 height bug fix</title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
$(function() {
function fixHeightOnIOS7() {
var fixedHeight = Math.min(
$(window).height(),
window.innerHeight || Infinity
);
$('body').height(fixedHeight);
}
$(window).on('resize orientationchange', fixHeightOnIOS7);
fixHeightOnIOS7();
// Generate content
var contentHTML = $('#content').html();
for (var i = 0; i < 8; i++) contentHTML += contentHTML;
$('#content').html(contentHTML);
});
</script>
<style>
html,
body
{
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: auto;
position: fixed;
}
#page-wrapper
{
height: 100%;
position: relative;
background: #aaa;
}
#header,
#footer
{
position: absolute;
width: 100%;
height: 30px;
background-color: #666;
color: #fff;
}
#footer
{
bottom: 0;
}
#content
{
position: absolute;
width: 100%;
top: 30px;
bottom: 30px;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
</style>
</head>
<body>
<div id="page-wrapper">
<div id="header">Header</div>
<div id="content">
<p>Lorem ipsum dolor sit amet.</p>
</div>
<div id="footer">Footer</div>
</div>
</body>
</html>