一段时间以来,我一直在为 iPad 中的固定定位而苦苦挣扎。我知道 iScroll,但它似乎并不总是有效(即使在他们的演示中)。我也知道 Sencha 对此有修复,但我无法 Ctrl + F 获得该修复的源代码。
我希望有人可能有解决方案。问题是当用户在 iOS 驱动的移动 Safari 上向下/向上平移时,固定定位的元素不会得到更新。
许多移动浏览器故意不支持 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
(但请注意,移动浏览器的世界发展非常迅速,所以像这样的表格可能不会长时间保持最新状态!)
更新:据报道,iOS 5 和 Android 4 现在都具有 position:fixed 支持。
我今天在 Apple Store 中自己测试了 iOS 5,可以确认它确实可以在位置固定的情况下工作。但是,放大和平移固定元素存在问题。
我发现这个兼容性表比 quirksmode 表更新和有用:http://caniuse.com/#search=fixed
它有关于 Android、Opera(迷你和移动)和 iOS 的最新信息。
固定定位在 iOS 上不像在计算机上那样工作。
想象一下,您在放大镜(视口)下有一张纸(网页),如果您移动放大镜和眼睛,您会看到页面的不同部分。这就是 iOS 的工作原理。
现在有一张透明塑料片,上面有一个字,这张塑料片无论如何都保持静止(位置:固定元素)。因此,当您移动放大镜时,固定元素似乎在移动。
或者,您不移动放大镜,而是移动纸张(网页),保持塑料片和放大镜不动。在这种情况下,塑料片上的单词会看起来保持不动,而其余的内容看起来会移动(因为它实际上是)这是一个传统的桌面浏览器。
所以在 iOS 中,视口在移动,在传统浏览器中,网页在移动。在这两种情况下,固定元素都保持在现实中;尽管在 iOS 上,固定元素似乎在移动。
解决此问题的方法是遵循 this article 中的最后几段
(基本上完全禁用滚动,将内容放在单独的可滚动 div 中(参见链接文章顶部的蓝色框),并且固定元素绝对定位)
"position:fixed" 现在可以像您在 iOS5 中所期望的那样工作。
position: fixed 在 android/iphone 上可以进行垂直滚动。但是您需要确保您的元标记已完全设置。例如
<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">
此外,如果您计划在 4.0 之前的 android 上使用相同的页面,您还需要设置顶部位置,否则由于某种原因会添加一个小边距。
user-scalable=0, minimum-scale=1.0, maximum-scale=1.0
禁止用户缩放会使许多用户无法访问该页面。在您的答案中添加有关它的警告会很有用
我在 Safari (iOS 10.3.3) 上遇到了这个问题 - 浏览器在触发 touchend 事件之前不会重绘。固定元素未出现或被截断。
对我来说,诀窍是添加 transform: translate3d(0,0,0);到我的固定位置元素。
.fixed-position-on-mobile {
position: fixed;
transform: translate3d(0,0,0);
}
编辑 - 我现在知道转换解决问题的原因:硬件加速。添加 3D 转换会触发 GPU 加速,从而实现平滑过渡。有关硬件加速检查的更多信息,请查看本文:http://blog.teamtreehouse.com/increase-your-sites-performance-with-hardware-accelerated-css。
fixed
时在 iOS 设备上弹跳,添加了 transform
并已修复。
现在苹果支持
overflow:hidden;
-webkit-overflow-scrolling:touch;
background-size: cover
和 fixed
问题所追求的
overflow
设置为 scroll
固定页脚(这里使用 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()
{
var iPadPosition = window.innerHeight + window.pageYOffset-45; // 45 is the height of the Footer
$("#fixedDiv").css("position", "absolute");
$("#fixedDiv").css("top", iPadPosition);
$("#fixedDiv").css("display", "block");
}
}
// in the CSS file should stand:
#fixedDiv {position: fixed; bottom: 0; height: 45px; whatever else}
避免在同一个盒子上使用 transform:--- 和 position:fixed。如果有任何变换,元素将保持在 position:static 中。
我最终使用了新的 jQuery Mobile v1.1:http://jquerymobile.com/blog/2012/04/13/announcing-jquery-mobile-1-1-0/
我们现在有一个可靠的重写,它在许多流行平台上提供真正的固定工具栏,并安全地回退到其他浏览器中的静态工具栏定位。这种方法最酷的部分是,与基于 JS 的解决方案在所有平台上强加不自然的滚动物理特性不同,我们的滚动感觉是 100% 原生的,因为它是。这意味着滚动感觉无处不在,并且适用于触摸、鼠标滚轮和键盘用户输入。作为奖励,我们基于 CSS 的解决方案是超轻量级的,不会影响兼容性或可访问性。
position:fixed
元素出现在滚动页面的前面,您只需要给它一个更高的 z-index
值,以便它保持在前面。
解决此问题的简单方法只是为您的元素键入转换属性。它将被修复。 .classname{ 位置:固定;变换:translate3d(0,0,0); }
你也可以试试他的方法,这也很好。
.classname{
position: -webkit-sticky;
}
使用 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 touch在横向还是纵向模式下会相应显示
<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>
尽管 CSS 属性 {position:fixed;}
似乎(大部分)适用于较新的 iOS 设备,但有时可能会出现设备怪癖并回退到 {position:relative;}
,而没有任何原因或原因。通常清除缓存会有所帮助,直到发生某些事情并且怪癖再次发生。
具体来说,来自 Apple 本身 Preparing Your Web Content for iPad:
iPad 上的 Safari 和 iPhone 上的 Safari 没有可调整大小的窗口。在 iPhone 和 iPad 上的 Safari 中,窗口大小设置为屏幕大小(减去 Safari 用户界面控件),用户无法更改。要在网页中移动,用户可以通过双击或捏合来放大或缩小,或者通过触摸和拖动来平移页面来更改视口的缩放级别和位置。当用户更改视口的缩放级别和位置时,他们是在固定大小的可视内容区域(即窗口)内进行的。这意味着其位置“固定”到视口的网页元素最终可能会出现在可视内容区域之外,即屏幕外。
具有讽刺意味的是,Android 设备似乎没有这个问题。此外,在引用 body 标记时完全可以使用 {position:absolute;}
并且没有任何问题。
我找到了这个怪癖的根本原因;与 HTML 或 BODY 标记结合使用时,滚动事件效果不佳。有时它不喜欢触发事件,或者您必须等到滚动摆动事件完成才能接收事件。具体来说,视口在此事件结束时重新绘制,并且固定元素可以重新定位在视口中的其他位置。
所以这就是我要做的:(避免使用视口,并坚持使用 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>
本质上,这将导致 BODY 成为视口的大小并且不可滚动。嵌套在里面的可滚动 DIV 将像 BODY 一样滚动(减去摇摆效果,所以滚动确实在 touchend 时停止。)固定 DIV 保持固定而不受干扰。
附带说明一下,固定 DIV 上的高 z-index
值对于保持可滚动 DIV 显示在其后面很重要。我通常会添加窗口调整大小和滚动事件,以实现跨浏览器和备用屏幕分辨率的兼容性。
如果所有其他方法都失败了,上面的代码也适用于设置为 {position:absolute;}
的固定和可滚动 DIV。
这可能不适用于所有场景,但我发现 position: sticky
(与 position: fixed
相同)仅在滚动容器不是主体,而是在其他东西内部时适用于旧 iPhone .
示例伪 html:
body <- scrollbar
relative div
sticky div
粘性 div 将在桌面浏览器上具有粘性,但在某些设备上测试过:Chromium:开发工具:设备仿真:iPhone 6/7/8,而使用 Android 4 Firefox,则不会。
然而,什么会起作用的是
body
div overflow=auto <- scrollbar
relative div
sticky div
就我而言,这是因为使用动画显示了固定元素。如in this link所述:
在 Safari 9.1 中,在动画元素中包含 position:fixed-element 可能会导致 position:fixed-element 不出现。
在 Iphone X 上遇到了同样的问题。要修复它,我只需向容器添加高度
top: 0;
height: 200px;
position: fixed;
我刚刚添加了 top:0 因为我需要我的 div 保持在顶部
这似乎适用于 iOS 12.4.2 上的 iphone 6 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>
不定期副业成功案例分享
position:device-fixed
有点多余。position:fixed
应该只符合 W3C 规范。device-fixed
解决方案不是我回答的一部分。它可能有也可能没有建议,但链接的原因是对问题的解释,而不是他建议的解决方案。无论如何,自从发布此答案(正如我所说的那样)以来,事情已经发生了很大变化,并且许多较新的设备确实支持fixed
。不过,您仍然需要处理不需要的旧设备。