Tổng quan
Cải thiện trải nghiệm người dùng đối với các nút nổi, chẳng hạn như đường liên kết "Quay lại đầu trang", bằng cách chỉ hiển thị các nút đó khi chúng hữu ích. Hướng dẫn này trình bày cách tạo các phần tử này bằng CSS container-scroll-state-queries, cho phép tạo kiểu cho các phần tử dựa trên vị trí cuộn của vùng chứa mà không cần dựa vào trình quan sát hoặc trình nghe cuộn JavaScript.
Triển khai
1. Thiết lập vùng chứa cuộn
Vùng chứa cuộn phải được khai báo là vùng chứa truy vấn trạng thái cuộn.
.scroller {
overflow-y: auto;
/* Establish this element as a scroll-state query container */
container-type: scroll-state;
}
2. Tạo kiểu cho phần tử nổi
Đặt phần tử bên trong vùng chứa và tạo kiểu cho phần tử đó. Theo mặc định, bạn nên ẩn chế độ này.
.back-to-top {
position: sticky;
bottom: 20px;
visibility: hidden;
opacity: 0;
translate: 0 20px;
transition:
visibility 0.3s,
opacity 0.3s ease,
translate 0.3s ease;
}
3. Phản hồi trạng thái cuộn
Sử dụng quy tắc @container với hàm scroll-state. Để kiểm tra xem người dùng đã cuộn xuống hay chưa, hãy kiểm tra xem vùng chứa có thể cuộn lên trên cùng hay không.
/* When the container can be scrolled toward the top, it means the user has scrolled down */
@container scroll-state(scrollable: top) {
.back-to-top {
visibility: visible;
opacity: 1;
translate: 0 0;
}
}
Chiến lược dự phòng
Dự phòng cơ bản
Nếu container-scroll-state-queries không được hỗ trợ, thì phần tử nổi sẽ vẫn không hiển thị do visibility: hidden mặc định. Để đảm bảo chức năng, bạn có thể chọn đặt phần tử luôn hiển thị trong các trình duyệt không được hỗ trợ.
/* Fallback for browsers that do not support the feature */
.back-to-top {
visibility: visible; /* Always visible */
opacity: 1;
}
/* Override for supported browsers to handle dynamic visibility */
@supports (container-type: scroll-state) {
.back-to-top {
visibility: hidden;
opacity: 0;
}
@container scroll-state(scrollable: top) {
.back-to-top {
visibility: visible;
opacity: 1;
translate: 0 0;
}
}
}
Dự phòng nâng cao (Intersection Observer)
Nếu cần có chế độ hiển thị linh động, hãy sử dụng IntersectionObserver để bật/tắt một lớp khi phần tử sentinel ở đầu trình cuộn nằm ngoài khung hiển thị.
<!-- Sentinel element placed at the top of the scroller -->
<div class="scroll-sentinel"></div>
/* Marker styling to ensure it does not affect layout */
.scroll-sentinel {
height: 0;
width: 0;
visibility: hidden;
}
.scrolled .back-to-top {
visibility: visible;
opacity: 1;
translate: 0 0;
}
if (!CSS.supports('container-type', 'scroll-state')) {
const sentinel = document.querySelector('.scroll-sentinel');
const scroller = document.querySelector('.scroller');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
// If the sentinel is NOT intersecting, it means the user has scrolled down
if (!entry.isIntersecting) {
scroller.classList.add('scrolled');
} else {
scroller.classList.remove('scrolled');
}
});
}, { root: scroller });
observer.observe(sentinel);
}