Harap dicatat bahwa postingan blog ini diterbitkan pada Juni 2015, jadi tergantung kapan Anda membacanya, beberapa bagian mungkin sudah kedaluwarsa. Sayangnya, saya tidak selalu dapat memperbarui postingan ini untuk memastikan keakuratan informasinya.
- Halaman Uji Coba Saya
- Memahami Perilaku Bawaan
- Memahami Apa yang Dilakukan Aturan CSS "-webkit-overflow-scrolling"
- Pengguna perlu menunggu hingga efek rubber-band selesai
- Cara Mencegah Halaman Latar Belakang Menggulir
- Cara mencegah gulir berlebih ke halaman latar belakang.
- Cara Mencegah Gulir Berlebih ke Halaman Latar Belakang
- Seluruh kode sumber halaman
Untuk memperbaiki masalah pengguliran yang baru-baru ini terjadi di Safari pada iOS, saya terpaksa membuat halaman tes sederhana sendiri dan kemudian menerapkan semua informasi serta kombinasi yang bisa saya temukan di internet untuk mencoba menyelesaikan masalah tersebut.
Berikut ini adalah gambaran singkat mengenai apa yang saya temukan selama proses ini.
Halaman Uji Coba Saya
Halaman tes saya cukup sederhana. Itu terdiri dari data tiruan di dalam sebuah div statis untuk mewakili 'halaman', beserta sebuah div tetap untuk mewakili 'menu' yang ditumpuk di atas halaman, seperti ini.
Kode sumber lengkap untuk halaman ini dapat ditemukan di bagian bawah posting blog ini.
Memahami Perilaku Bawaan
Hal pertama yang saya lakukan adalah mencoba memahami perilaku default Safari di iOS. Pengamatan yang paling menonjol adalah ketika Anda menggulir hingga ke bagian bawah menu, badan halaman menunjukkan "efek karet" - sebuah fitur bawaan di Safari.
Hal yang sama juga terjadi saat Anda menggulir ke bagian paling atas menu.
Namun, masalah pertama yang saya perhatikan adalah jika Anda terus menggulir hingga ke bagian atas atau bawah secara terus-menerus, Safari mulai menampilkan gangguan rendering pada halaman latar belakang maupun menu.
Saya tidak yakin mengapa, tetapi saya menduga itu terkait dengan fitur efek peregangan.
Memahami Apa yang Dilakukan Aturan CSS "-webkit-overflow-scrolling"
Langkah berikutnya yang saya lakukan adalah menerapkan aturan CSS -webkit-overflow-scrolling pada menu, yang mengaktifkan pengguliran berbasis momentum.
Seperti yang terlihat pada gambar di bawah, gulir tetap berjalan meskipun saya menggesek layar dengan jari.
Namun, efek rubber-band juga muncul saat menggulir ke bagian atas atau bawah, seperti yang terlihat di bawah ini.
Pengguna perlu menunggu hingga efek rubber-band selesai
Selama pengujian saya, saya juga memperhatikan bahwa saat efek rubber-band sedang berlangsung, pengguna tidak dapat mengalihkan fokus ke elemen lain hingga animasinya selesai sepenuhnya.
Di contoh di bawah ini, saya pertama-tama menggulir halaman latar belakang dan kemudian mencoba menggulir menu dengan cepat, tetapi pada akhirnya saya tetap menggulir halaman latar belakang.
Namun, jika saya menunggu sebentar hingga efeknya selesai, saya bisa mulai menggulir menu.
Cara Mencegah Halaman Latar Belakang Menggulir
Selama pengujian saya, saya juga melihat bahwa saat efek karet sedang berlangsung, pengguna tidak bisa mengalihkan fokus ke elemen lain hingga animasinya selesai sepenuhnya.
Berdasarkan jawaban berikut dari Stack Overflow, Anda bisa memastikan bahwa elemen dengan disable-scrolling tidak melakukan aksi gulir bawaan saat peristiwa touchmove dipicu.
document.ontouchmove = function(event) {
var isTouchMoveAllowed = true,
target = event.target;
while (target !== null) {
if (target.classList && target.classList.contains('disable-scrolling')) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}
if (!isTouchMoveAllowed) {
event.preventDefault();
}
};
Kemudian terapkan kelas disable-scrolling pada elemen div halaman:
<div class="page disable-scrolling">
Ini cukup berfungsi, tetapi pengujian yang lebih luas menunjukkan bahwa halaman latar belakang masih bisa digulir sesekali saat Anda mencapai bagian atas atau bawah menu.
Cara mencegah gulir berlebih ke halaman latar belakang.
Dengan menerapkan perbaikan ini fix, menjadi mungkin untuk mencegah "overscrolling". Ini berarti ketika sebuah elemen digulir hingga bagian atas atau bawahnya, gulir tidak berlanjut ke badan halaman.
Akibatnya, isi halaman tidak bisa digulir, dan efek band karet juga tidak muncul.
function removeIOSRubberEffect(element) {
element.addEventListener("touchstart", function() {
var top = element.scrollTop,
totalScroll = element.scrollHeight,
currentScroll = top + element.offsetHeight;
if (top === 0) {
element.scrollTop = 1;
} else if (currentScroll === totalScroll) {
element.scrollTop = top - 1;
}
});
}
removeIOSRubberEffect(document.querySelector(".scrollable"));
Potongan kode JavaScript ini mencegah elemen mencapai tepi atas maupun tepi bawah dengan menjaga jaraknya tetap hanya 1 piksel.
Jika posisi gulir tidak pernah mencapai bagian atas atau bawah secara mutlak, overscroll tidak akan pernah terjadi.
Cara Mencegah Gulir Berlebih ke Halaman Latar Belakang
Jika Anda ingin menghilangkan efek rubber-band pada menu—baik karena alasan estetika maupun karena, seperti yang saya alami, itu menimbulkan gangguan rendering tambahan—cukup hapus aturan CSS -webkit-overflow-scrolling.
Namun, seperti yang bisa Anda lihat di bawah, Anda juga kehilangan kelancaran gulir.
Seluruh kode sumber halaman
Berikut adalah kode sumber lengkap untuk halaman ini.
<!-- License MIT, Author Special Agent Squeaky (specialagentsqueaky.com) --> <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="minimum-scale=1.0, width=device-width, maximum-scale=1.0, user-scalable=no, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style> .page{ font-size: 24px; overflow: scroll; } .menu{ position: fixed; top: 0; bottom: 0; left: 0; width: 80%; background: gray; z-index: 1; font-size: 10px; overflow: scroll; /* uncomment to get smooth momentum scroll, but also a rubber band effect */ /*-webkit-overflow-scrolling: touch;*/ } .menu-item{ padding: 10px; background: darkgray; font-size: 24px; } </style>
</head>
<body>
<div class="menu scrollable">
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
</div>
<div class="page disable-scrolling">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and scrambled it to make a type
specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged. It was popularised in
the 1960s with the release of Letraset sheets containing Lorem Ipsum passages,
and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</div>
<script>
document.ontouchmove = function(event) {
var isTouchMoveAllowed = true,
target = event.target;
while (target !== null) {
if (target.classList && target.classList.contains('disable-scrolling')) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}
if (!isTouchMoveAllowed) {
event.preventDefault();
}
};
function removeIOSRubberEffect(element) {
element.addEventListener("touchstart", function() {
var top = element.scrollTop,
totalScroll = element.scrollHeight,
currentScroll = top + element.offsetHeight;
if (top === 0) {
element.scrollTop = 1;
} else if (currentScroll === totalScroll) {
element.scrollTop = top - 1;
}
});
}
removeIOSRubberEffect(document.querySelector(".scrollable"));
</script>
</body>
</html>