ตัวบ่งชี้ความคืบหน้าในการเลื่อนเป็นรูปแบบอินเทอร์เฟซผู้ใช้ที่พบบ่อยซึ่งสื่อสารความคืบหน้าของผู้ใช้ผ่านเอกสารหรือคอนเทนเนอร์ที่เลื่อนได้ด้วยภาพ เมื่อผู้ใช้เลื่อน องค์ประกอบภาพจะอัปเดตเพื่อแสดงตำแหน่งของผู้ใช้ ซึ่งช่วยให้ผู้ใช้ทราบได้อย่างชัดเจนและเข้าใจง่ายว่าดูเนื้อหาไปแล้วเท่าใดและเหลืออีกเท่าใด
วิธีการนำไปใช้งาน
หากต้องการสร้างตัวบ่งชี้ความคืบหน้าในการเลื่อน คุณต้องมี 2 สิ่งต่อไปนี้
- องค์ประกอบที่ทำหน้าที่เป็นแถบความคืบหน้า โดยทั่วไปองค์ประกอบนี้จะเป็น
position: fixedหรือposition: absoluteเพื่อให้อยู่ในมุมมองขณะที่ผู้ใช้เลื่อนดูเนื้อหา - ภาพเคลื่อนไหวที่ลิงก์กับตำแหน่งการเลื่อน
ซึ่งคุณสามารถทำได้ดังนี้
- ก่อนอื่น ให้สร้างองค์ประกอบ HTML ที่จะทำหน้าที่เป็นแถบความคืบหน้า คุณจัดสไตล์องค์ประกอบนี้ได้ตามต้องการ
- ถัดไป ใน CSS ให้กำหนดภาพเคลื่อนไหว
@keyframesที่ปรับขนาดแถบความคืบหน้า แนวทางที่พบบ่อยคือการปรับขนาดองค์ประกอบจากscaleX(0)เป็นscaleX(1) - สุดท้าย ให้ใช้ภาพเคลื่อนไหวนี้กับองค์ประกอบแถบความคืบหน้าและตั้งค่า
animation-timelineเป็น scroll-timeline ซึ่งจะบอกให้เบราว์เซอร์ขับเคลื่อนความคืบหน้าของภาพเคลื่อนไหวตามตำแหน่งการเลื่อนของตัวเลื่อนระดับบนสุดที่ใกล้ที่สุด
โค้ดตัวอย่าง
โค้ดนี้จะขยายองค์ประกอบ #progress เมื่อเลื่อนโดยใช้ไทม์ไลน์การเลื่อนแบบไม่ระบุตัวตน ซึ่งสร้างโดยฟังก์ชัน scroll()
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: scroll())) {
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
#progress {
position: fixed;
left: 0; top: 0;
width: 100%; height: 1em;
background: red;
transform-origin: 0 50%;
animation: grow-progress auto linear;
animation-timeline: scroll();
}
}
}
เนื่องจากตำแหน่งใน DOM ฟังก์ชัน scroll() จะติดตามตัวเลื่อนระดับบนสุดที่ใกล้ที่สุดในทิศทาง block ซึ่งในที่นี้คือตัวเลื่อนระดับราก
<body>
<!-- MANDATORY: Purely decorative visual scroll progress bars MUST set aria-hidden="true" to remove the empty element from the assistive technology reading tree -->
<div id="progress" aria-hidden="true"></div>
</body>
โค้ดนี้จะขยายองค์ประกอบ #progress เมื่อเลื่อนโดยใช้ไทม์ไลน์การเลื่อนที่มีชื่อ ซึ่งสร้างโดยพร็อพเพอร์ตี้ scroll-timeline
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: scroll())) {
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
:root {
scroll-timeline: --tl block;
}
#progress {
position: fixed;
left: 0; top: 0;
width: 100%; height: 1em;
background: red;
transform-origin: 0 50%;
animation: grow-progress auto linear;
animation-timeline: --tl;
}
}
}
แนวทางปฏิบัติแนะนำ
เมื่อใช้ภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน คุณควรทำตามแนวทางปฏิบัติแนะนำต่อไปนี้เพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ราบรื่นและเข้าถึงได้
- ควรรวมการตรวจหาฟีเจอร์: เบราว์เซอร์บางรายการไม่รองรับภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน ใช้
@supports (animation-timeline: scroll())เพื่อตรวจสอบการรองรับและระบุตัวเลือกสำรองสำหรับเบราว์เซอร์ที่ไม่รองรับ- อย่าใช้แพ็กเกจ
scroll-timeline-polyfillสำหรับกลยุทธ์สำรอง เนื่องจากฟีเจอร์ยังไม่สมบูรณ์และมีปัญหาที่ทราบอยู่แล้วจำนวนมาก - หากภาพเคลื่อนไหวถือเป็นเพียงการตกแต่ง ให้เลือกใช้การเพิ่มประสิทธิภาพแบบต่อเนื่อง และอย่าระบุทางเลือกสำรอง
- อย่าใช้แพ็กเกจ
- ควรนำองค์ประกอบที่ใช้เพื่อการตกแต่งเท่านั้นออกจากขั้นตอนการอ่านของเทคโนโลยีความช่วยเหลือพิเศษ โดยใช้
aria-hidden="true"กับตัวบ่งชี้การเลื่อนที่เป็นภาพเท่านั้น เพื่อให้โปรแกรมอ่านหน้าจอไม่พบโหนดที่ว่างเปล่าและไม่มีชื่อ - ควรเคารพค่ากำหนดของผู้ใช้: ผู้ใช้บางรายต้องการให้มีการเคลื่อนไหวน้อยลงบนเว็บ ใช้คิวรีสื่อ
prefers-reduced-motionเพื่อปิดใช้หรือลดภาพเคลื่อนไหวสำหรับผู้ใช้เหล่านี้ - ควรพยายามทำให้เฉพาะพร็อพเพอร์ตี้ CSS ที่มีประสิทธิภาพเคลื่อนไหว: เพื่อให้ภาพเคลื่อนไหวราบรื่นที่สุด ให้ใช้พร็อพเพอร์ตี้ที่เคลื่อนไหวซึ่งจัดการได้โดยเทรด Compositor ของเบราว์เซอร์ เช่น
transformและopacityการทำให้พร็อพเพอร์ตี้อื่นๆ เช่นwidthหรือheightเคลื่อนไหวอาจทำให้เกิดปัญหาด้านประสิทธิภาพ - ควรใช้ลำดับการประกาศที่ถูกต้อง: เมื่อใช้พร็อพเพอร์ตี้ชวเลข
animationให้ประกาศanimation-timelineหลังจากพร็อพเพอร์ตี้ดังกล่าวเพื่อป้องกันไม่ให้ชวเลขรีเซ็ตไทม์ไลน์
เมื่อใช้ฟังก์ชัน scroll() เพื่อสร้างภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน ให้ทำดังนี้
- ไม่บังคับ ระบุตัวเลื่อนอย่างชัดเจน: เมื่อไม่ได้กำหนดเป้าหมายตัวเลื่อนระดับบนสุดที่ใกล้ที่สุด ให้ระบุตัวเลื่อนที่ต้องการใช้อย่างชัดเจนด้วย
scroll(root)หรือscroll(self)- เมื่อ
root,nearestหรือselfไม่เพียงพอ ให้ใช้ scroll-timeline ที่มีชื่อ
- เมื่อ
- ไม่บังคับ ระบุแกนที่จะติดตามอย่างชัดเจน: เมื่อไม่ได้กำหนดเป้าหมายแกน
blockเริ่มต้น (เช่น ในแถบเลื่อนแนวนอน) ให้ระบุแกนที่จะติดตามอย่างชัดเจนด้วยscroll(block)หรือscroll(inline)
เมื่อใช้พร็อพเพอร์ตี้ scroll-timeline เพื่อสร้างภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน ให้ทำดังนี้
- ควรใช้ CSS
<dashed-ident>สำหรับชื่อ - ไม่บังคับ ระบุแกนที่จะติดตามอย่างชัดเจน: เมื่อไม่ได้กำหนดเป้าหมายแกน
blockเริ่มต้น (เช่น ในแถบเลื่อนแนวนอน) ให้ระบุแกนที่จะติดตามด้วยscroll-timeline-axisอย่างชัดเจน - ควรตรวจสอบว่าขอบเขตของการค้นหาใช้งานได้: เมื่อองค์ประกอบที่ประกาศ
scroll-timelineไม่ใช่ระดับบนสุดแบบ Flat Tree ขององค์ประกอบที่เคลื่อนไหว ให้เพิ่มระดับการมองเห็นชื่อของscroll-timelineโดยใช้timeline-scopeในระดับบนสุดที่ใช้ร่วมกัน
กลยุทธ์สำรอง
สำหรับเบราว์เซอร์ที่ไม่รองรับภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน คุณสามารถใช้โหมดสำรองเพื่อสร้างเอฟเฟกต์ภาพขึ้นมาใหม่ได้ โดยปกติแล้ว ฟังก์ชันสำรองจะสร้างขึ้นด้วย Listener การเลื่อน (สำหรับเอฟเฟกต์ ScrollTimeline) หรือ IntersectionObserver API (สำหรับเอฟเฟกต์ ViewTimeline)
ในเบราว์เซอร์ที่มีการรองรับภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อนในตัว ให้ใช้การติดตั้งใช้งาน CSS แบบเนทีฟเสมอ เนื่องจากมีประสิทธิภาพมากกว่า
โปรดทราบว่าคุณไม่สามารถสร้างเอฟเฟกต์ทั้งหมดขึ้นมาใหม่ได้โดยใช้วิธีการสำรอง
สำหรับ Use Case นี้โดยเฉพาะ สคริปต์ต่อไปนี้จะใช้โหมดสำรองสำหรับเบราว์เซอร์ที่ไม่รองรับภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน โดยจะใช้ Listener การเลื่อนเพื่อติดตามตำแหน่งการเลื่อนขององค์ประกอบรูทและอัปเดตพร็อพเพอร์ตี้ transform ของแถบความคืบหน้าตามลำดับ
<script>
if (!CSS.supports('animation-timeline', 'scroll()')) {
const progress = document.querySelector('#progress');
window.addEventListener('scroll', () => {
const scrollable = document.documentElement.scrollHeight - window.innerHeight;
const scrolled = window.scrollY;
const progressPercentage = (scrolled / scrollable);
progress.style.transform = `scaleX(${progressPercentage})`;
});
}
</script>