2017-07-22 59 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

相關問題