CSS3属性webkit-overflow-scrolling:touch错误

62

iOS 5发布了一个新的属性-webkit-overflow-scrolling:touch,利用iOS设备的硬件加速器为可滚动的div提供本地滚动。

在我们正在开发的网站上实现时,它确实可以工作,但效果不好。我认为可能存在CSS问题,因此在这里询问。

以下代码片段将向您展示其正常工作

如果您在iOS上访问我们正在开发中的网站,您将在"设施"选项卡下找到相同的面板,尽管滚动非常完美,但溢出部分没有显示图片,并且图片被切成两半。

http://www.golfbrowser.com/courses/mill-ride/

我不知道如何修复这个问题。 http://www.golfbrowser.com/photo.PNG


1
我在iOS6上遇到了类似的问题(相关页面在iOS5上正常工作)。通过为被截断的img标签应用-webkit-transform:translate3d(0,0,0)来解决,现在可以正常工作了。 - codebox
8个回答

94

正如@relluf指出的那样,在相对定位的元素上应用3D转换可以修复此错误。然而,我进一步调查了一下,似乎应用-webkit-transform: translateZ(0px)也可以解决问题(这是Google在gmaps地图容器上使用的方法),并且不需要放在相对定位的元素上,只需放在可滚动元素的直接后代元素上即可。

因此,如果您不想手动维护所有需要进行修复的位置列表,您只需执行以下操作:

element {
    -webkit-overflow-scrolling: touch;
}

element > * {
    -webkit-transform: translateZ(0px);
}

4
我觉得element > *有点问题。虽然它解决了剪切问题,但滚动元素在滚动时会闪烁。我通过将硬件加速应用于所有元素来修复了闪烁问题:element *(无直接子选择器)。 - Pwner
1
这有点让我想起了过去不得不在元素上加zoom:1来解决hasLayout问题的老日子。:( - bkdraper
这帮了我很多...但我有一个问题。我也想实现像视差滚动效果一样滚动背景图片,但是它会出现颤抖?有什么帮助吗? - Ahsan Khurshid
3
这绝非一个好的解决方案,因为它会向浏览器创建更多渲染层,并让GPU需要做更多的图层合成工作!移动设备的GPU内存较低,不会很好地支持此项功能。请参阅http://aerotwist.com/blog/on-translate3d-and-layer-creation-hacks/。 - Sebastien Lorber
3
这个解决方案真的很糟糕。选择器极其低效,会生成大量GPU渲染层。 - Aaron
显示剩余5条评论

18

这里出现了一个麻烦的 bug。我试了各种方法来解决,最终发现在 -webkit-overflow-scrolling:touch 的 div 中,唯一需要正确呈现元素的属性是: position: static

相对定位和绝对定位的元素总是被修剪在边界上,在边界外则完全缺失(除了空白区域)。如果您动态地将 position 属性从 static 更改为 absolute,则仅在滚动的 div 视口中可见的部分保持呈现,不管偏移量在哪里。


4
这对我很有帮助,我从一些输入元素中删除了position: relative(将它们保留为默认的position: static),它们在滚动过程中可以正确地呈现出来。 - Paul

6

我也遇到了这个bug。我通过将以下css应用于父元素来解决它:

-webkit-transform: translate3d(0, 0, 0);

然而,我注意到这会减慢渲染速度,并且在 Safari/iOS 中,当触摸的输入元素滚动到视图中心时,可能会选择其他输入元素。


4
对我来说,这个方法很有效,在 -webkit-overflow-scrolling: touch 容器内的 position: relative 元素上进行设置。 - samy-delux
请忽略“当触摸输入元素滚动到视图中心时,可能会选择其他输入元素而不是所需的”部分。我弄错了。 - relluf

3

在iOS中,当一个带有-webkit-overflow-scrolling: touch属性的元素内部包含一个绝对定位(或固定定位)于滚动容器之外的元素时,该元素将仅呈现一次,而随着元素的滚动,其渲染不会更新。示例HTML:

<div class="relative-to-me">
  <div class="scrollable">
    <div class="absolutely-positioned">
    </div>
  </div>
</div>

如果你改变CSS属性(例如在检查器中)强制重新渲染,你会发现元素的定位被重新渲染到正确的位置。我怀疑这是一些性能特性,可以优化滚动性能。
解决这个问题的方法是在绝对定位(或固定定位)元素上设置will-change: transform
.absolutely-positioned {
    will-change: transform;
}

这对我来说似乎很奇怪,因为你从未更改过 transform 属性,或者我们更改了吗? - gmustudent

2

1
错误仍然存在于iOS 6中。如果您的问题与“position: relative”有关,则可以通过使用JS临时设置“z-index: 1”来解决该问题。-webkit-transform: translate(...)在我的情况下无法与position: relative一起使用。

1

我也遇到了一个问题,即使用-webkit-overlfow-scrolling设置为touch的overflow scroll会导致定位元素的重绘问题。在我的情况下,我有一个列表,其中各个项目具有相对定位,以便我可以在它们的子元素上使用定位。在iOS 5上使用上述CSS时,当用户将隐藏内容滚动到视图中时,屏幕重新绘制元素之前会有短暂的延迟。这真的很烦人。幸运的是,我发现如果我也给父节点设置相对位置,这个问题就解决了。


0

我尝试了一些不同的解决方案,但在我的情况下似乎都不完美。

最终,我找到了一个使用jQuery很好的方法:

每次触摸结束时应用-webkit-overflow-scrolling属性。

*起初,我还在TouchDown时应用了-webkit-overflow-scrolling:auto来禁用iOS渲染。但这会导致页面闪烁。所以我放弃了它,然后惊奇地发现它可以正常工作!

请查看下面的代码行,希望能有所帮助:

<!--  JQuery Functions-->

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">

// Apply -webkit-overflow-scrolling in Every TouchEnd
$(document).on('click touchend', function(event) {
    $("#TestDIV").css({"-webkit-overflow-scrolling":"touch"});
});

</script>



<!--  html Elements & Style -->

<div id="TestDIV">
    <div class="Element"></div>
    <div class="Element"></div>
    <div class="Element"></div>
    <div class="Element"></div>
    <div class="Element"></div>
</div>

<style>
#TestDIV{
    white-space: nowrap;
    overflow-x: scroll;
    -webkit-overflow-scrolling:touch;
}

#TestDIV .Element{
    width:300px;
    height:300px;

    margin: 2px;

    background-color: gray;

    display: inline-block;
}
#TestDIV .Element:nth-child(odd){
    background-color: whitesmoke;
}   
</style>

这对我的情况很有帮助(在文本框中输入文本时出现文本消失的问题),因为它会由于React设置中CSS更改而导致重新渲染。然而,我不得不先将其设置为auto,然后再设置为touch。发现这个问题在iOS 13中已经修复了。 - Evan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接