位置: 固定不能在 iPad 和 iPhone 上工作

我一直在为 iPad 的固定定位而苦苦挣扎。我知道 IScroll,它似乎并不总是工作(即使在他们的演示)。我也知道,Sencha 有一个修复,但我不能 Ctrl + F的源代码,该修复。

我希望有人能解决这个问题。问题是,当用户在 iOS 驱动的移动 Safari 上向下/向上平移时,固定位置的元素不会得到更新。

354222 次浏览

许多移动浏览器故意不支持 position:fixed;,理由是固定元素可能会在小屏幕上造成阻碍。

QuirkSmode.org 网站有一篇非常好的博客文章,解释了这个问题: http://www.quirksmode.org/blog/archives/2010/12/the_fifth_posit.html

此外,请参阅本页的兼容性图表,其中显示了哪些移动浏览器支持 position:fixed;: http://www.quirksmode.org/m/css.html

(但是请注意,移动浏览器世界的发展非常迅速,所以像这样的表格可能不会保持很长时间的最新状态!)

更新: 据报道,iOS5和 Android 4目前都有固定的支持。

今天我自己在苹果商店里测试了 iOS5系统,可以确认它确实可以在固定位置下工作。但是,在固定元素周围放大和平移存在一些问题。

我发现这个兼容性表格比那个古怪模式表格更新更有用: Http://caniuse.com/#search=fixed

它有最新的 Android,Opera (迷你和移动)和 iOS 信息。

固定位置在 iOS 上不像在电脑上那样起作用。

想象你有一张纸(网页)在放大镜(视窗)下面,如果你移动放大镜和你的眼睛,你会看到网页的不同部分。这就是 iOS 的工作原理。

现在有一张透明的塑料板,上面有一个单词,这张塑料板无论什么(位置: 固定元素)都保持不动。所以当你移动放大镜的时候固定元素 abc0会移动。

或者,你可以不移动放大镜,而是移动纸张(网页) ,使塑料和放大镜保持静止。在这种情况下,塑料板上的文字看起来是固定的,其余的内容看起来是移动的(因为它确实是移动的)这是一个传统的桌面浏览器。

所以在 iOS 系统中视图移动,在传统浏览器中网页移动。在这两种情况下,固定元素仍然停留在现实中; 尽管在 iOS 上,固定元素似乎在移动。


解决这个问题的方法是按照 这篇文章中的最后几段

(基本上完全禁用滚动,将内容放在一个单独的可滚动 div 中(参见链接文章顶部的蓝色框) ,并将固定元素绝对定位)


“ position: fix”现在可以像 iOS5一样工作了。

位置: 固定工作在 android/iphone 的垂直滚动。但是您需要确保您的 meta 标签已经完全设置好了。例如:

<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">

另外,如果你打算在 android pre 4.0上使用相同的页面,你也需要设置页面的顶部位置,否则由于某些原因,会添加一个小的页边距。

现在苹果公司支持这一点

overflow:hidden;
-webkit-overflow-scrolling:touch;

使用 jquery 我可以得到这个。它不是滚动平滑,但它做的诀窍。你可以向下滚动,固定的 div 就会出现在顶部。

CSS

<style type="text/css">
.btn_cardDetailsPg {height:5px !important;margin-top:-20px;}
html, body {overflow-x:hidden;overflow-y:auto;}
#lockDiv {
background-color: #fff;
color: #000;
float:left;
-moz-box-shadow: 0px 4px 2px 2px #ccc;-webkit-box-shadow: 0px 4px 2px 2px #ccc;box-shadow:0px 4px 2px 2px #ccc;
}
#lockDiv.stick {
position: fixed;
top: 0;
z-index: 10000;
margin-left:0px;
}
</style>

HTML

<div id="lockSticky"></div>
<div id="lockDiv">fooo</div>

查询

<script type="text/javascript">
function sticky_relocate() {
var window_top = $(window).scrollTop();
var div_top = $('#lockSticky').offset().top;
if (window_top > div_top)
$('#lockDiv').addClass('stick')
else
$('#lockDiv').removeClass('stick');
}
$(function() {
$(window).scroll(sticky_relocate);
sticky_relocate();
});
</script>

最后,我们要确定是否在横向或纵向模式下显示相应的 ipod 触摸

<script type="text/javascript">
if (navigator.userAgent.match(/like Mac OS X/i)) {
window.onscroll = function() {


if (window.innerWidth > window.innerHeight) {
//alert("landscape [ ]");
document.getElementById('lockDiv').style.top =
(window.pageYOffset + window.innerHeight - 268) + 'px';
}


if (window.innerHeight > window.innerWidth) {
//alert("portrait ||");
document.getElementById('lockDiv').style.top =
(window.pageYOffset + window.innerHeight - 418) + 'px';
}
};
}
</script>

我最终使用了新的 jQuery Mobile v1.1: http://jquerymobile.com/blog/2012/04/13/announcing-jquery-mobile-1-1-0/

我们现在已经有了一个可靠的重写,它提供了真正的固定工具栏 许多流行的平台和安全回落到静态工具栏 在其他浏览器中定位。

这种方法最酷的地方在于,与基于 JS 的方法不同 这些解决方案将非自然的滚动物理学强加于所有 平台,我们的滚动感觉100% 原生,因为它 。这意味着 滚动的感觉无处不在,并与触摸,鼠标轮工作 和键盘用户输入。作为奖励,我们的 CSS 为基础的解决方案是超级 轻量级,不影响兼容性或可访问性。

尽管 CSS 属性 {position:fixed;}似乎(大多数情况下)可以在较新的 iOS 设备上工作,但设备偶尔也可能出现异常,或者无缘无故地退回到 {position:relative;}。通常清除缓存会有所帮助,直到某些事情发生,怪事再次发生。

具体来说,来自苹果自身的 为 iPad 准备网页内容:

IPad 上的 Safari 和 iPhone 上的 Safari 都没有可调窗口 在 iPhone 和 iPad 上的 Safari 中,窗口大小被设置为 屏幕(减去 Safari 用户界面控件) ,并且不能更改 要在网页上移动,用户需要更改缩放级别 当他们双击或捏放大或 或者通过触摸和拖动来平移页面。当用户改变时 视图的缩放级别和位置 固定大小的可视内容区域(即窗口)。这意味着 该网页元素的位置“固定”到视窗 可以结束在可视内容区域之外,离开屏幕。

具有讽刺意味的是,Android 设备似乎没有这个问题。另外,当引用 body 标记时,完全可以使用 {position:absolute;},而且没有任何问题。

我发现了这个怪现象的根本原因: 滚动事件在与 HTML 或 BODY 标记结合使用时不能很好地发挥作用。有时它不喜欢触发事件,或者您必须等到滚动摇摆事件完成后才能接收事件。具体来说,视口在这个事件结束时被重新绘制,并且固定的元素可以在视口中的其他地方被重新定位。

这就是我要做的: (避免使用 viewport,坚持使用 DOM!)

<html>
<style>
.fixed{
position:fixed;
/*you can set your other static attributes here too*/
/*like height and width, margin, etc.*/
}
.scrollableDiv{
position:relative;
overflow-y:scroll;
/*all children will scroll within this like the body normally would.*/
}
.viewportSizedBody{
position:relative;
overflow:hidden;
/*this will prevent the body page itself from scrolling.*/
}
</style>
<body class="viewportSizedBody">
<div id="myFixedContainer" class="fixed">
This part is fixed.
</div>
<div id="myScrollableBody" class="scrollableDiv">
This part is scrollable.
</div>
</body>
<script type="text/javascript" src="{your path to jquery}/jquery-1.7.2.min.js"></script>
<script>
var theViewportHeight=$(window).height();
$('.viewportSizedBody').css('height',theViewportHeight);
$('#myScrollableBody').css('height',theViewportHeight);
</script>
</html>

从本质上说,这将导致主体的大小视窗和不可滚动。嵌套在里面的可滚动 DIV 将像正常的主体一样滚动(减去摆动效果,所以滚动在触摸端停止)固定的 DIV 保持固定,没有干扰。

顺便说一句,固定 DIV 上的高 z-index值对于保持可滚动 DIV 显示在其后面很重要。我通常添加窗口大小和滚动事件也为跨浏览器和替代屏幕分辨率兼容性。

如果所有其他方法都失败了,那么上面的代码也将用于设置为 {position:absolute;}的固定和可滚动 DIV。

固定页脚(这里有 jQuery) :

if (navigator.platform == 'iPad' || navigator.platform == 'iPhone' || navigator.platform == 'iPod' || navigator.platform == 'Linux armv6l') {
window.ontouchstart = function() {
$("#fixedDiv").css("display", "none");
}


window.onscroll = function() {
// 45 is the height of the Footer
var iPadPosition = window.innerHeight + window.pageYOffset-45;


$("#fixedDiv").css("position", "absolute");
$("#fixedDiv").css("top", iPadPosition);
$("#fixedDiv").css("display", "block");
}
}

在 CSS 文件中应该是:

 #fixedDiv {
position: fixed;
bottom: 0;
height: 45px;
...
}

避免在同一个框中使用转换: ——-和 position: fix。如果有任何转换,元素将保持位置: static。

我在 Safari (iOS10.3.3)上遇到了这个问题——直到触摸事件触发,浏览器才重新绘制。固定元素没有出现或被切断。

对我来说,诀窍在于向我的固定位置元素添加转换: transate3d (0,0,0) ; 。

.fixed-position-on-mobile {
position: fixed;
transform: translate3d(0,0,0);
}

EDIT -我现在知道为什么转换修复了这个问题: 硬件加速。添加3D 转换触发 GPU 加速使平稳过渡。有关硬件加速的更多信息,请参阅本文: http://blog.teamtreehouse.com/increase-your-sites-performance-with-hardware-accelerated-css

解决这个问题的简单方法就是为你的元素输入转换属性。

.classname{
position: fixed;
transform: translate3d(0,0,0);
}

也可以试试他的方法,以及这也是工作的罚款。

.classname {
position: -webkit-sticky;
}

这可能不适用于所有场景,但是我发现 position: sticky(与 position: fixed相同)只能在老款 iPhone 上使用,当滚动容器是 没有主体时,但是在其他东西内部。

示例伪 html:

body                         <- scrollbar
relative div
sticky div

粘性 div 在桌面浏览器上会非常粘性,但是在某些设备上,经过 Chromium: dev tools: 设备模拟: iPhone 6/7/8和 Android 4 Firefox 的测试,它不会粘性。

然而,有效的办法是

body
div overflow=auto       <- scrollbar
relative div
sticky div

在我的例子中,这是因为固定元素是通过动画来显示的:

在 Safari 9.1中,在动画元素中有一个 position: fix-element,可能会导致 position: fix-element 不出现。

在 IphoneX 上也有同样的问题。为了修复它,我只需要给容器增加高度

top: 0;
height: 200px;
position: fixed;

我刚刚加了 top: 0,因为我需要我的 div 保持在最高

这似乎适用于 iOS12.4.2上的 iPhone6 Plus 上的 Ionic5

.large_player {
float: left;
bottom: 0;
width: 100%;
position: fixed;
background-color: white;
border-top: black 1px solid;
height: 14rem;
z-index: 100;
transform: translate3d(0,0,0);
}

transform标签使它工作,但它似乎也有点笨重的滚动如何工作,它似乎是重新绘制的’顶部’元素后,它的所有移动和排序重置,使它跳跃一点点。

或者,你也可以使用这个标签选项,position: -webkit-sticky;,但是你不会得到,或者可能遇到麻烦与 WPA/浏览器或 Android 构建,而不得不做版本检查和有多个 CSS 标签。

.large_player {
float: left;
bottom: 0;
width: 100%;
position: -webkit-sticky;
background-color: white;
border-top: black 1px solid;
height: 14rem;
z-index: 100;
}

我不知道它是在什么时候修好的,但是后来 iOS 手机没有转换标签就可以工作了。我不知道是 iOS 版本还是手机。

由于大多数 iOS 设备通常使用最新的 iOS 版本,所以使用一些奇怪的方法是相当安全的——比如使用 transform标签,而不是为了不到1% 的用户而建立一个奇怪的检测程序。

更新:

在进一步思考这个问题的答案之后,这只是在 ionic5 + 平台上做这件事的另一种方式:

。 TS

import {Platform } from '@ionic/angular';


constructor(public platform: Platform) {
// This next bit is so that the CSS is shown correctly for each platform


platform.ready().then(() => {
if (this.platform.is('android')) {
console.log("running on Android device!");
this.css_iOS = false;
}
if (this.platform.is('ios')) {
console.log("running on iOS device!");
this.css_iOS = true;
}
if (this.platform.is('ipad')) {
console.log("running on iOS device!");
this.css_iOS = true;
}
});
}
css_iOS: boolean = false;

。 HTML

<style *ngIf="css_iOS">
.small_player {
position: -webkit-sticky !important;
}
.large_player {
position: -webkit-sticky !important;
}
</style>
    

    

<style>
.small_player {
float: left;
bottom: 0;
width: 100%;
position: fixed;
background-color: white;
border-top: black 1px solid;
height: 4rem;
z-index: 100;
/*transform: translate3d(0,0,0);*/
}
    

.large_player {
float: left;
bottom: 0;
width: 100%;
position: fixed;
background-color: white;
border-top: black 1px solid;
height: 14rem;
z-index: 100;
/*transform: translate3d(0,0,0);*/
}
</style>