Người nghiện Internet chuyên nghiệp • Người đam mê trò chơi • Người sáng tạo công nghệ
Người nghiện Internet chuyên nghiệp • Người đam mê trò chơi • Người sáng tạo công nghệ

Sáu điều tôi học được về cuộn co giãn của iOS Safari

Để khắc phục vấn đề cuộn trên Safari khi dùng iOS, tôi buộc phải tự mình tạo một trang thử nghiệm đơn giản!
Trang này đã được các thực tập sinh AI đầy nhiệt huyết của tôi dịch từ tiếng Anh để thuận tiện cho bạn. Các bạn vẫn đang trong quá trình học hỏi, nên có thể còn một vài lỗi nhỏ. Để có thông tin chính xác nhất, vui lòng tham khảo phiên bản tiếng Anh.
Trang chủ Blog Sáu điều tôi học được về cuộn co giãn của iOS Safari

Xin lưu ý rằng bài đăng trên blog này được xuất bản vào tháng 6 năm 2015, vì vậy tùy thuộc vào thời điểm bạn đọc, một số phần có thể đã lỗi thời. Rất tiếc, tôi không thể luôn cập nhật đầy đủ các bài đăng này để đảm bảo thông tin luôn chính xác.

Để khắc phục một sự cố cuộn gần đây trên Safari dành cho iOS, tôi buộc phải tự tạo một trang thử nghiệm đơn giản của riêng mình và sau đó áp dụng tất cả thông tin cũng như các cách kết hợp mà tôi có thể tìm thấy trên Internet để cố gắng giải quyết vấn đề.

Dưới đây là một cái nhìn tổng quan ngắn gọn về những gì tôi đã phát hiện trong quá trình này.

Trang thử nghiệm của tôi

Trang thử nghiệm của tôi khá cơ bản. Nó gồm dữ liệu giả được đặt trong một thẻ div tĩnh để đại diện cho 'trang', cùng với một thẻ div cố định đại diện cho một 'menu' chồng lên phía trên trang, như thế này.

Một ảnh chụp màn hình của menu bên HTML đang được mở trên iOS Safari

Toàn bộ mã nguồn cho trang này có thể được tìm thấy ở cuối bài viết trên blog này.

Hiểu về hành vi mặc định

Điều đầu tiên tôi làm là cố gắng hiểu hành vi mặc định của Safari trên iOS. Nhận xét nổi bật nhất là khi bạn cuộn đến tận cùng menu, phần thân của trang sẽ thể hiện một "hiệu ứng đàn hồi" - một tính năng được lập trình sẵn trong Safari.

một ảnh chụp màn hình động cho thấy hiện tượng đàn hồi gây khó chịu ở iOS Safari ở cuối trang

Điều tương tự cũng xảy ra khi cuộn đến đỉnh của menu.

một ảnh chụp màn hình động cho thấy hiệu ứng đàn hồi (rubber band) gây sự cố trong iOS Safari ở đầu trang

Tuy nhiên, vấn đề đầu tiên tôi nhận thấy là nếu bạn cuộn liên tục lên tận đầu trang hoặc xuống tận cuối trang, Safari sẽ bắt đầu gặp các lỗi hiển thị ở cả trang nền và menu.

Tôi không chắc tại sao, nhưng tôi nghĩ nó có liên quan đến hiệu ứng co giãn.

một ảnh chụp màn hình động cho thấy vấn đề Safari trên iOS bị lỗi ở cuối trang

Hiểu tác dụng của thuộc tính CSS "-webkit-overflow-scrolling"

Điều tiếp theo tôi đã làm là áp dụng quy tắc CSS -webkit-overflow-scrolling cho menu, điều này kích hoạt cuộn theo động lượng.

Như hình dưới đây cho thấy, việc cuộn vẫn tiếp tục ngay cả khi tôi vuốt bằng ngón tay.

hiển thị vấn đề cuộn quán tính trên iOS Safari

Nhưng nó cũng tạo hiệu ứng đàn hồi khi cuộn lên đến đỉnh trang hoặc xuống đến đáy trang, như hình bên dưới.

minh họa vấn đề cuộn dựa trên động lực trên iOS Safari với hiệu ứng đàn hồi

Người dùng cần đợi cho đến khi hiệu ứng đàn hồi kết thúc

Trong quá trình thử nghiệm, tôi cũng nhận thấy rằng khi hiệu ứng đàn hồi đang diễn ra, người dùng không thể chuyển tiêu điểm sang phần tử khác cho đến khi hoạt ảnh hoàn tất.

Trong ví dụ dưới đây, tôi cuộn trang nền trước, sau đó thử cuộn menu một cách nhanh chóng, nhưng lại tiếp tục cuộn trang nền.

hiển thị rằng trang nền được cuộn thay vì trên iOS Safari

Tuy nhiên, nếu tôi đợi một chút cho hiệu ứng kết thúc, tôi có thể bắt đầu cuộn menu.

trình diễn quá trình chờ cho hiệu ứng đàn hồi kết thúc trên iOS Safari

Cách ngăn trang nền khỏi bị cuộn

Trong quá trình thử nghiệm, tôi cũng nhận thấy rằng khi hiệu ứng đàn hồi đang diễn ra, người dùng không thể chuyển sự tập trung sang phần tử khác cho đến khi hoạt ảnh kết thúc hoàn toàn.

Dựa trên câu trả lời này từ Stack Overflow, bạn có thể đảm bảo rằng các phần tử có lớp disable-scrolling sẽ không thực hiện hành động cuộn mặc định khi sự kiện touchmove được kích hoạt.

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(); } };

Và sau đó áp dụng lớp disable-scrolling cho thẻ div của trang:

<div class="page disable-scrolling">

Cái này hoạt động khá ổn, nhưng thử nghiệm mở rộng hơn cho thấy trang nền vẫn có thể cuộn thỉnh thoảng khi bạn đến đỉnh hoặc đáy của menu.

hiển thị cho thấy phông nền vẫn đang được cuộn

Cách ngăn cuộn quá mức sang trang nền

Bằng cách áp dụng biện pháp sửa lỗi, chúng ta có thể ngăn chặn hiện tượng cuộn quá mức. Điều này có nghĩa là khi một phần tử được cuộn tới đỉnh hoặc đáy của nó, việc cuộn sẽ không tiếp tục vào phần thân của trang.

Do đó, trang web sẽ không cho phép cuộn, và điều này cũng ngăn hiện tượng đàn hồi (rubber-band) xảy ra.

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"));

Đoạn mã JavaScript này khiến phần tử không bao giờ chạm đến đỉnh hoặc đáy bằng cách giữ nó cách mép trên và mép dưới đúng 1 pixel.

Nếu vị trí cuộn không bao giờ chạm đến đỉnh tuyệt đối hoặc đáy tuyệt đối, việc cuộn quá mức sẽ không xảy ra.

ví dụ về việc ngăn chặn cuộn quá mức bằng cách không bao giờ chạm vào đầu trang hoặc cuối trang

Cách ngăn cuộn quá mức sang trang nền

Nếu bạn muốn loại bỏ hiệu ứng đàn hồi của menu — cho lý do thẩm mỹ hoặc vì, như trong trường hợp của tôi, nó gây ra thêm các lỗi hiển thị — chỉ cần xóa quy tắc CSS -webkit-overflow-scrolling.

Tuy nhiên, như bạn có thể thấy ở phía dưới, bạn cũng mất đi sự mượt mà khi cuộn.

demo đầy đủ cho việc ngăn hiện tượng đàn hồi khi cuộn trên iOS Safari

Toàn bộ mã nguồn của trang

Dưới đây là toàn bộ mã nguồn của trang.

<!-- 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>

Được viết bởi Special Agent Squeaky. Đăng lần đầu ngày 10/06/2015. Cập nhật lần cuối ngày 10/06/2015.

📺 Xem video mới nhất của Squeaky!

Cách thêm phụ đề thời gian thực cho phát trực tiếp của bạn một cách đơn giản