2017-07-22 30 views
1

请考虑以下情形:一个简单的解决方案,以防止Safari上的身体滚动

您有2个可滚动元素。

  1. 附着到$项的长流动的列表(文件).scroll()
  2. 一个单独的容器/重叠侦听$( “类”)。滚动()

enter image description here

具有以下CSS属性。

body { 
overflow-y: scroll; 
height: 100%; 
} 

.class { 
height: 100%; /* 50% 20% 200px whatever you may */ 
position: fixed; 
overflow-y: scroll; 
-webkit-overflow-scrolling: touch; 
} 

换句话说,一个非常标准的建立,在2017年应该工作,没有任何设备上的任何问题。错了。

下面是我通过几年的经历与这个简单的设置问题,并没有找到一个良好的,可靠的解决方案:

  1. 叠加启动时滚动从轻微到极端闪烁顶部底部覆盖当100%高度,无论所有iDevices的HTML复杂性。 (因为过度滚动的z-index问题或硬件加速问题,我不知道)。
  2. 在顶部或底部为了等待身体滚动停止过度滚动时,滚动会完全停止。
  3. 如果容器的滚动错误地停止(whilist过度滚动),并且用户保持滚动,则主体将滚动,导致用户体验非常不一致,因为用户现在最终会到达其他位置比打开覆盖层之前的身体滚动。同时也不得不停止滚动以等待过度滚动停止。

  4. 如果容器是100%的高度,并且没有滚动 - 如果用户启动 滚动,身体会滚动,滚动条将是可见的,但 页面貌似不滚动,导致不一致的用户体验 。

我试过的一些解决方案没有任何成功。

  1. iScroll。 iScroll通过防止文档上的任何触摸事件来停止过度滚动问题。但提供不一致和不良滚动体验imho。除此之外,它甚至不再需要。
  2. 其他可以想象的滚动插件。
  3. 事件委托 - 尝试仅为正在与之交互的元素启用滚动。在桌面上工作。不可移动的Safari浏览器。
  4. 可以想象每个jQuery滚动助手。温和的成功,但非常不一致。

看来,无论什么修复过去已经提出,以某种方式贬值为“各种原因”(不意味着声音阴谋。)

我读了几个星期前,苹果正在开发的更新的 滚动的WebKit的,使其跨越各类 内容类型的更均匀的iPhone服务。但在此之前,这个简单的设置在移动Safari上仍然存在问题。

我可能最终想出了一个解决方案。不过我很好奇,想听到别人是如何在2017年解决这个问题...

+1

如果您添加了附带的HTML,那将非常有用。考虑添加一个片段。谢谢 –

+0

你真的认为这是必要的吗?就我而言,这是一个广为人知的问题。让我知道你的想法。 – Crashtor

+0

是的,我确实认为。 (这是3小时后,你没有答案..)但我现在出去,所以我不再使用..后来! –

回答

1

我会在这里添加评论,因为这看起来像问题最近,很好的概述(感谢的!)

我也尝试了几乎所有你所说的并最终找到了解决方案。 基本上,你需要设置你的主容器和覆盖层的大小,使它们都为fixed并给它们overflow: auto,这样文件本身从不滚动

  • 当覆盖层关闭时,内容会在放置的主容器内滚动。 (使用height: 100vh; width: 100vw;top/left/bottom/right: 0;以及box-sizing: border-box;可帮助使其不显眼)。
  • 当您打开叠加层时,将主容器切换为overflow: hidden,此时叠加层内的内容将滚动。再次,文件本身从来没有。

这有一个缺点:地址栏永远不会隐藏在iOS上。我相信这仍然是一个更好的体验,因为它始终保持一致。

此外,如果您从可滚动区域外部开始滚动,则需要关注焦点,iOS的橡皮条效果会阻止后续与页面的交互,直至完成橡皮圈。 (其他地方有帖子解释了如何解决这个问题 - 监视滚动事件,如果它到达顶部,则将元素向下按1px,如果在底部则向上移动1px。)

let openBtns = document.getElementsByClassName('open'), 
 
    closeBtns = document.getElementsByClassName('close'), 
 
    overlay = document.getElementById('overlay'); 
 

 

 
for (let btn of openBtns) { 
 
    btn.onclick =() => { 
 
     document.body.classList.add('overlay-open'); 
 
     overlay.setAttribute('aria-hidden', false); 
 
    }; 
 
} 
 

 
for (let btn of closeBtns) { 
 
    btn.onclick =() => { 
 
     document.body.classList.remove('overlay-open'); 
 
     overlay.setAttribute('aria-hidden', true); 
 
    }; 
 
}
#page, #overlay { 
 
    position: fixed; 
 
    top: 0; bottom: 0; left: 0; right: 0; 
 
    margin: auto; 
 
    box-sizing: border-box; 
 
    overflow: auto; 
 
    font-size: 4em; 
 
    -webkit-overflow-scrolling: touch; 
 
} 
 

 
#page { 
 
    padding: 1rem 2rem 2rem; 
 
} 
 

 
.overlay-open > #page { 
 
    position: fixed; 
 
    filter: blur(5px); 
 
    overflow: hidden; 
 
    pointer-events: none; 
 
} 
 

 
#overlay { 
 
    display: none; 
 
    padding: 2rem; 
 
    font-size: 2em; 
 
} 
 

 
#overlay > .content { 
 
    position: relative; 
 
    width: 20em; 
 
    margin: auto; 
 
    padding: 0 1rem 1rem; 
 
    background-color: rgba(200, 0, 255, 0.5); 
 
} 
 

 
.overlay-open > #overlay { 
 
    display: block; 
 
}
<body> 
 
    <div id="page"> 
 
     <div class="content"> 
 
      <button class="open">Open overlay</button> 
 
      <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p> 
 
      <button class="open">Open overlay</button> 
 
     </div> 
 
    </div> 
 
    <div id="overlay" aria-hidden="true"> 
 
     <div class="content"> 
 
      <button class="close">Close overlay</button> 
 
      <p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.</p> 
 
      <button class="close">Close overlay</button> 
 
     </div> 
 
    </div> 
 
</body>

(要知道那里面有一些CSS,这只是必要的片段在这里或Codepen意义,基本上一切,不是位置/溢出相关的是作秀,它应该很容易弄清楚,但可以随时要求澄清)

+0

是的,这基本上是我解决这个问题的方法,同时保存主要的内容的滚动位置,因为当禁用滚动时,页面会自动滚动到顶部。然而,这不是一个完美的解决方案,我发现iOS设备上的机身惯性依然活跃。因此,如果您向下滚动到底部,请等到弹跳效果完全停止。向下滚动然后再滚动,整个视图卡住了。并且从我所做的所有研究来看。这取决于苹果解决这个问题,因为它根本就没有办法解决。 – Crashtor

+0

不需要额外的JS,就我所知,在这个例子中,页面不会跳回到开头。这是我之前遇到的一个问题,不幸的是我不记得解决它的确切的事情,但是无论如何,我认为这个实现没有这个问题。 (编辑)至于惯性,是的,这就是我提到的橡皮筋 - 但就像我说的,防止元素实际达到顶部/底部的这种拙劣的方式应该有所帮助? – Acccent

+0

至少在移动Safari浏览器中,当您溢出时,页面将跳转回scrollTop 0:隐藏;在一个元素上......但它看起来并不像在桌面版本上发生的那样。 – Crashtor

相关问题