在移动Safari上的固定位置div内滚动内容突然停止 - 并开始滚动容器本身

时间:2022-11-10 21:26:37

I have a container which has position:fixed with scrolling content inside. I'm displaying this as a chat feature on mobile devices but on mobile Safari, the scrolling content inside the position:fixed container stops scrolling suddenly and starts to scroll the container itself.

我有一个容器,其位置:固定滚动内容。我在移动设备上将其显示为聊天功能,但在移动设备上,位置内的滚动内容:固定容器突然停止滚动并开始滚动容器本身。

Open this link on mobile Safari to see the effect: http://jsbin.com/ruyito

在移动版Safari上打开此链接以查看效果:http://jsbin.com/ruyito

Editable example here: http://jsbin.com/ruyito/edit?html,css,output

可编辑示例:http://jsbin.com/ruyito/edit?html,css,output

The question: Why does my container div start to scroll its position suddenly and stop scrolling the content? (On Chrome on Android, it works without issue)

问题:为什么我的容器div开始突然滚动它的位置并停止滚动内容? (在Android上的Chrome上,它没有问题)

Note: if you're having trouble triggering this bug, keep scrolling the content up and down quickly for 10 seconds or so, eventually it will suddenly stop scrolling.

注意:如果您在触发此错误时遇到问题,请继续快速上下滚动内容10秒左右,最终会突然停止滚动。

4 个解决方案

#1


3  

I've come across this issue several times when trying to use use overflow: scroll div's in iOS Safari.

我在尝试使用use overflow时多次遇到过这个问题:在iOS Safari中滚动div。

My understanding it that it's to do with the overscrolling/elastic scrolling animations. What seems to happen is:

我理解它与过度滚动/弹性滚动动画有关。似乎发生的事情是:

  1. When a certain container (i.e. the window, or your scrolling div) is running these animations the events get locked to that container.
  2. 当某个容器(即窗口或滚动div)运行这些动画时,事件将锁定到该容器。
  3. When an overflow: scroll container hits the top/bottom of it's scroll height it then starts scrolling the parent container - this is also the case in Chrome.
  4. 当溢出:滚动容器点击其滚动高度的顶部/底部时,它会开始滚动父容器 - 这也是Chrome中的情况。

You may notice in your example that when the scrolling stops working, not touching the screen for a small amount of time (say 500ms?) then trying to scroll again works.

您可能会注意到在您的示例中,当滚动停止工作时,没有触摸屏幕一小段时间(比如500毫秒?)然后尝试再次滚动工作。

What I think is happening is that when you hit the bottom/top of your scrolling container, the events are getting locked to the parent, in this case the window. While you keep interacting in this state, your events never make it to your scrolling container, and so it appears to be unresponsive.

我认为发生的事情是当你点击滚动容器的底部/顶部时,事件将被锁定到父级,在这种情况下是窗口。当您在此状态下保持交互时,您的事件永远不会进入滚动容器,因此它似乎没有响应。

I've had some success in the past by not propagating the touch events from my scrolling container up to the document:

过去我没有将滚动容器中的触摸事件传播到文档中,从而取得了一些成功:

$('.chat-container-mobile').on({
    'touchstart': _onTouchStart,
    'touchmove': _onTouchMove,
    'touchend': _onTouchEnd
});

function _onTouchStart(e) {

    e.stopPropagation();
}

function _onTouchMove(e) {

    e.stopPropagation();
}

function _onTouchEnd(e) {

    e.stopPropagation();
}

Note: This will not be a fix in many situations, as you often need to retain default window behaviour. In this case though, you seem to have a fixed layout which doesn't require default document scrolling behaviour. Additionally, you will likely still see the same result if you attempt to scroll by touching on the top 'Group chat' bar or bottom 'Type message' bar, then quickly afterwards try to scroll within your container.

注意:在许多情况下,这不是一个修复,因为您经常需要保留默认窗口行为。但在这种情况下,您似乎有一个固定的布局,不需要默认的文档滚动行为。此外,如果您尝试通过触摸顶部的“群组聊天”栏或底部的“键入消息”栏进行滚动,您可能仍会看到相同的结果,然后很快尝试在您的容器内滚动。

You could also try using e.preventDefault on $(document) for these touch events. This prevents the window from reacting to these user inputs in the first place, again though this can cause many other problems if you need to retain browser defaults.

您还可以尝试在$(文档)上使用e.preventDefault来处理这些触摸事件。这样可以防止窗口首先响应这些用户输入,但如果您需要保留浏览器默认值,这可能会导致许多其他问题。

Also try to localise these bindings only in situations where it's a problem. So check for iOS and Safari before binding onto the events.

还尝试仅在出现问题的情况下本地化这些绑定。因此,在绑定到事件之前检查iOS和Safari。

I'll come back with any extra findings the next time I try to deal with the the problem - which, let's be honest, is almost every project.

下次我尝试处理这个问题时,我会带回任何额外的发现 - 诚然,这几乎是每个项目。

Good luck!

祝你好运!

#2


1  

I dont quite know what the deal is here. It might be that safari freezes when moving it that quickly because it still technically moves the container the way it should by the inspector tools definition, just does not portray it on the screen.

我不太清楚这笔交易是什么。可能是safari在快速移动时会冻结,因为它在技术上仍然按照检查器工具定义的方式移动容器,只是不会在屏幕上描绘它。

One thing you could try that I did in the inspector tools and seems to solve the issue is reverse engineering what you have. Try this changeup to your code. note the positioning/height/padding on your .chat-container-mobile and z-index/bottom/positioning on the other two elements.

你可以尝试我在检查工具中做的一件事似乎解决了这个问题是逆向工程你所拥有的。尝试对您的代码进行此更改。注意.chat-c​​ontainer-mobile上的定位/高度/填充和其他两个元素上的z-index / bottom / positioning。

<style>
.chat-container-mobile {
position: fixed;
background-color: #EBEBEB;
padding: 15px;
display: block;
margin: 0;
top: 0px;
color: #444444;
overflow: scroll;
-webkit-overflow-scrolling: touch;
height: calc(100vh - 50px);
padding: 75px 15px 125px;
}
.chat-mobile-header {
position: fixed;
z-index: 10;
width: 100%;
background-color: white;
color: #444444;
text-transform: uppercase;
letter-spacing: 0.04em;
font-size: 15px;
font-weight: 500;
text-align: center;
top: 0;
margin: 0;
padding: 17px 0;
border-bottom: 1px solid rgba(68, 68, 68, 0.2);
}
.chat-field-mobile {
position: fixed;
width: 100%;
z-index: 10;
bottom: 0;
margin: 0px;
padding: 12px 12px 10px 10px;
background-color: #EBEBEB;
border-top: 1px solid rgba(68, 68, 68, 0.1);
}
</style>

doing it this way those other elements just lie on top of your chat window instead of trying to stack or force your pieces together.

这样做,其他元素只是位于聊天窗口的顶部,而不是试图堆叠或强制你的碎片。

Hope this helps mate!

希望这有助于交配!

#3


1  

Just try to add bottom:0 to .chat-container-mobile { bottom:0 }

只需尝试添加底部:0到.chat-c​​ontainer-mobile {bottom:0}

#4


1  

I opened the link ( http://jsbin.com/ruyito) iPhone 6 - Safari and everything looks fine. Content scrolls as expected. I tried many times up and down scroll but nothing happened.

我打开了链接(http://jsbin.com/ruyito)iPhone 6 - Safari,一切看起来都很好。内容按预期滚动。我上下滚动了很多次,但没有发生任何事情。

At which version this happens? I couldn't say anything without experience the bug but i think it can be virtual scroll issue.

这会发生在哪个版本?如果没有经验,我无法说出任何错误,但我认为这可能是虚拟滚动问题。

You can disable this by adding this.

你可以通过添加它来禁用它。

.chat-container-mobile {
    -moz-transition: none;
    -webkit-transition: none;
    -o-transition: color 0 ease-in;
    transition: none;
}

#1


3  

I've come across this issue several times when trying to use use overflow: scroll div's in iOS Safari.

我在尝试使用use overflow时多次遇到过这个问题:在iOS Safari中滚动div。

My understanding it that it's to do with the overscrolling/elastic scrolling animations. What seems to happen is:

我理解它与过度滚动/弹性滚动动画有关。似乎发生的事情是:

  1. When a certain container (i.e. the window, or your scrolling div) is running these animations the events get locked to that container.
  2. 当某个容器(即窗口或滚动div)运行这些动画时,事件将锁定到该容器。
  3. When an overflow: scroll container hits the top/bottom of it's scroll height it then starts scrolling the parent container - this is also the case in Chrome.
  4. 当溢出:滚动容器点击其滚动高度的顶部/底部时,它会开始滚动父容器 - 这也是Chrome中的情况。

You may notice in your example that when the scrolling stops working, not touching the screen for a small amount of time (say 500ms?) then trying to scroll again works.

您可能会注意到在您的示例中,当滚动停止工作时,没有触摸屏幕一小段时间(比如500毫秒?)然后尝试再次滚动工作。

What I think is happening is that when you hit the bottom/top of your scrolling container, the events are getting locked to the parent, in this case the window. While you keep interacting in this state, your events never make it to your scrolling container, and so it appears to be unresponsive.

我认为发生的事情是当你点击滚动容器的底部/顶部时,事件将被锁定到父级,在这种情况下是窗口。当您在此状态下保持交互时,您的事件永远不会进入滚动容器,因此它似乎没有响应。

I've had some success in the past by not propagating the touch events from my scrolling container up to the document:

过去我没有将滚动容器中的触摸事件传播到文档中,从而取得了一些成功:

$('.chat-container-mobile').on({
    'touchstart': _onTouchStart,
    'touchmove': _onTouchMove,
    'touchend': _onTouchEnd
});

function _onTouchStart(e) {

    e.stopPropagation();
}

function _onTouchMove(e) {

    e.stopPropagation();
}

function _onTouchEnd(e) {

    e.stopPropagation();
}

Note: This will not be a fix in many situations, as you often need to retain default window behaviour. In this case though, you seem to have a fixed layout which doesn't require default document scrolling behaviour. Additionally, you will likely still see the same result if you attempt to scroll by touching on the top 'Group chat' bar or bottom 'Type message' bar, then quickly afterwards try to scroll within your container.

注意:在许多情况下,这不是一个修复,因为您经常需要保留默认窗口行为。但在这种情况下,您似乎有一个固定的布局,不需要默认的文档滚动行为。此外,如果您尝试通过触摸顶部的“群组聊天”栏或底部的“键入消息”栏进行滚动,您可能仍会看到相同的结果,然后很快尝试在您的容器内滚动。

You could also try using e.preventDefault on $(document) for these touch events. This prevents the window from reacting to these user inputs in the first place, again though this can cause many other problems if you need to retain browser defaults.

您还可以尝试在$(文档)上使用e.preventDefault来处理这些触摸事件。这样可以防止窗口首先响应这些用户输入,但如果您需要保留浏览器默认值,这可能会导致许多其他问题。

Also try to localise these bindings only in situations where it's a problem. So check for iOS and Safari before binding onto the events.

还尝试仅在出现问题的情况下本地化这些绑定。因此,在绑定到事件之前检查iOS和Safari。

I'll come back with any extra findings the next time I try to deal with the the problem - which, let's be honest, is almost every project.

下次我尝试处理这个问题时,我会带回任何额外的发现 - 诚然,这几乎是每个项目。

Good luck!

祝你好运!

#2


1  

I dont quite know what the deal is here. It might be that safari freezes when moving it that quickly because it still technically moves the container the way it should by the inspector tools definition, just does not portray it on the screen.

我不太清楚这笔交易是什么。可能是safari在快速移动时会冻结,因为它在技术上仍然按照检查器工具定义的方式移动容器,只是不会在屏幕上描绘它。

One thing you could try that I did in the inspector tools and seems to solve the issue is reverse engineering what you have. Try this changeup to your code. note the positioning/height/padding on your .chat-container-mobile and z-index/bottom/positioning on the other two elements.

你可以尝试我在检查工具中做的一件事似乎解决了这个问题是逆向工程你所拥有的。尝试对您的代码进行此更改。注意.chat-c​​ontainer-mobile上的定位/高度/填充和其他两个元素上的z-index / bottom / positioning。

<style>
.chat-container-mobile {
position: fixed;
background-color: #EBEBEB;
padding: 15px;
display: block;
margin: 0;
top: 0px;
color: #444444;
overflow: scroll;
-webkit-overflow-scrolling: touch;
height: calc(100vh - 50px);
padding: 75px 15px 125px;
}
.chat-mobile-header {
position: fixed;
z-index: 10;
width: 100%;
background-color: white;
color: #444444;
text-transform: uppercase;
letter-spacing: 0.04em;
font-size: 15px;
font-weight: 500;
text-align: center;
top: 0;
margin: 0;
padding: 17px 0;
border-bottom: 1px solid rgba(68, 68, 68, 0.2);
}
.chat-field-mobile {
position: fixed;
width: 100%;
z-index: 10;
bottom: 0;
margin: 0px;
padding: 12px 12px 10px 10px;
background-color: #EBEBEB;
border-top: 1px solid rgba(68, 68, 68, 0.1);
}
</style>

doing it this way those other elements just lie on top of your chat window instead of trying to stack or force your pieces together.

这样做,其他元素只是位于聊天窗口的顶部,而不是试图堆叠或强制你的碎片。

Hope this helps mate!

希望这有助于交配!

#3


1  

Just try to add bottom:0 to .chat-container-mobile { bottom:0 }

只需尝试添加底部:0到.chat-c​​ontainer-mobile {bottom:0}

#4


1  

I opened the link ( http://jsbin.com/ruyito) iPhone 6 - Safari and everything looks fine. Content scrolls as expected. I tried many times up and down scroll but nothing happened.

我打开了链接(http://jsbin.com/ruyito)iPhone 6 - Safari,一切看起来都很好。内容按预期滚动。我上下滚动了很多次,但没有发生任何事情。

At which version this happens? I couldn't say anything without experience the bug but i think it can be virtual scroll issue.

这会发生在哪个版本?如果没有经验,我无法说出任何错误,但我认为这可能是虚拟滚动问题。

You can disable this by adding this.

你可以通过添加它来禁用它。

.chat-container-mobile {
    -moz-transition: none;
    -webkit-transition: none;
    -o-transition: color 0 ease-in;
    transition: none;
}