有時候我們的畫面會需要用到如下圖的 Modal 彈窗:
這樣的 Modal 彈窗,他的內容有可能是針對某個地方的額外說明,因此這個說明也有可能會需要詳細的描述,內容有可能會很長,所以為了不要讓內容超出 Modal 範圍,通常我們會選擇加上滾動條:
.modal {
overflow-y: auto;
}
從這個情境範例來看,當我們的 Modal 滾動到最底部的滾動邊界時,如果再繼續觸發滾動,我們就會發現,怎麼連背景也開始滾動了?
當我們滾動到 Modal 底部,再繼續對 Modal 滾動時,瀏覽器將繼續滾動主頁面的內容,這樣的行為稱為滾動穿透(scroll chaining)。這是一個瀏覽器默認的行為。
但是這樣的行為通常是不需要的,因為他會分散使用者對 Modal 內容的注意力。並且因為行為超出預期,使用者在操作時有時候也會嚇一跳。
其實除了上述 Modal 的例子之外,還有一些常見的例子也會容易發生滾動穿透。
下圖是一個側邊欄搭配對應的主頁內容。當我們的側邊欄是 fixed
在頁面上,並且主頁的內容超出範圍而變得主頁可滾動時,在側邊欄的滾動行為也很可能會觸發滾動穿透。
https://ishadeed.com/article/prevent-scroll-chaining-overscroll-behavior/
下拉選單也是容易發生滾動穿透的範例,通常下拉選單會是一個浮動在主頁之上的元件,當下拉選單滾動到最底部的時候,我們再繼續對選單滾動,也很可能會繼續觸發到背後主頁的滾動,造成使用者體驗不佳。
相信大家也看過這種在網頁上的聊天視窗,例如 Facebook 的網頁聊天室,或者某某電商網站跟賣家的聊天視窗,或是官網上面的客服聊天室等等。
聊天視窗的性質也是一個浮動的元件蓋在主頁上,當聊天視窗滾動到底部的時候再繼續滾動,也有機會觸發背景主頁的滾動,會讓使用者覺得,怎麼我在操作聊天視窗,背景卻不預期的在動?
由於滾動條是由 overflow
屬性造成的,只要我們設置 overflow: auto;
或者 overflow: scroll;
皆會讓內容超出的元件出現滾動條。
所以很直覺得方式就是我們能夠透過 Javascript 在我們希望避免滾動的元件上(例如 body)動態添加 overflowL hidden;
來解決這個問題。
例如,當一個 Modal 被開啟時,我們將背後的 body 設為 overflow: hidden;
:
body.modal-open {
overflow: hidden;
}
.modal.is-open {
display: block;
}
這個解決方案可以在桌面瀏覽器上完美的運行,但是如果網頁是開啟在 iOS 的 Safari 上,這樣的方法可能會失靈。因此,以上述為例,我們需要在 body 上面添加 position: fixed;
:
body.modal-open {
position: fixed;
overflow: hidden;
}
.modal.is-open {
display: block;
}
這個方法可行,但是當背景滾動到中間時若開啟 Modal,則會造成背景滾動到頂部,在操作感受上會分散使用者對 Modal 的注意力,整個體驗也會變得很奇怪。
overscroll-behavior
這個 CSS 屬性可以幫助我們控制元件滾動到滾動邊界(boundary of a scrolling area)時的行為。但在使用這個屬性時,我們要留意他的可用性,特別是在 Safari 以及 iOS Safari 上:
overscroll-behavior
是 overscroll-behavior-x
以及 overscroll-behavior-y
的縮寫,跟 overflow
一樣,可以控制兩個維度。
他的預設值是 overscroll-behavior: auto;
,就是允許滾動穿透,當一個可滾動的元素滾動到邊界時,瀏覽器將會繼續滾動他的父層,例如 body
的內容。
因此,我們可以在我們想要鎖定的元件上面添加 overscroll-behavior: contain;
,顧名思義就是我們的滾動只包含在該元件上:
.modal {
overscroll-behavior: contain;
}
另外,overscroll-behavior: none;
也能夠幫助我們阻止滾動穿透,並且他也同時會阻止滾動到邊界時的反彈及刷新頁面的效果:
.modal {
overscroll-behavior: none;
}
CSS overscroll-behavior
是一個很有用的屬性,過去我們需要透過複雜的 Hacky 方法才能夠解決滾動穿透,現在一行 CSS 就能夠解決這個問題。
今天也舉了幾個容易出現滾動穿透的例子,希望能夠幫助讀者延伸思考,也能夠多留意頁面上可能發生滾動穿透的情境。