เอฟเฟกต์การเข้าและออกคือภาพเคลื่อนไหวที่ทริกเกอร์เมื่อองค์ประกอบเข้าสู่หรือออกจากวิวพอร์ต ซึ่งสามารถใช้เพื่อสร้างประสบการณ์ของผู้ใช้ที่น่าสนใจและเป็นแบบไดนามิก เช่น คุณสามารถใช้เอฟเฟกต์ทางเข้าเพื่อทำให้องค์ประกอบค่อยๆ ปรากฏขึ้นเมื่อเลื่อนเข้ามาในมุมมอง หรือใช้เอฟเฟกต์ทางออกเพื่อลดขนาดองค์ประกอบเมื่อเลื่อนออกจากมุมมอง
วิธีการนำไปใช้งาน
หากต้องการเพิ่มเอฟเฟกต์ทางเข้าและทางออกให้กับองค์ประกอบ คุณต้องรวมพร็อพเพอร์ตี้ CSS 2-3 รายการเข้าด้วยกัน ต่อไปนี้คือคำแนะนำทีละขั้นตอน:
สร้าง
@keyframesแยกกันสำหรับภาพเคลื่อนไหวสำหรับการเข้าและออกฉาก ระบบจะใช้ภาพเคลื่อนไหวสำหรับการเข้าฉากเมื่อองค์ประกอบเข้าสู่วิวพอร์ต และจะใช้ภาพเคลื่อนไหวสำหรับการออกจากฉากเมื่อองค์ประกอบออกจากวิวพอร์ต@keyframes slide-in { from { transform: translateX(-100%); } } @keyframes slide-out { to { transform: translateX(100%); } }แนบคีย์เฟรมเข้าและออกกับองค์ประกอบ ซึ่งทำได้โดยกำหนดภาพเคลื่อนไหวหลายรายการในพร็อพเพอร์ตี้
animation- กำหนด
animation-fill-modeเป็นbackwardsให้กับภาพเคลื่อนไหวขาเข้า เพื่อให้ใช้สถานะเริ่มต้นก่อนที่ภาพเคลื่อนไหวจะเริ่ม - กำหนดให้ภาพเคลื่อนไหวขาออกมี
animation-fill-modeเป็นforwardsเพื่อให้คงสถานะสุดท้ายไว้หลังจากภาพเคลื่อนไหวเสร็จสมบูรณ์
.animated-element { animation: slide-in 1s linear backwards, slide-out 1s linear forwards; }- กำหนด
สร้าง View Timeline และลิงก์กับภาพเคลื่อนไหว ไทม์ไลน์มุมมองคือประเภทของไทม์ไลน์ที่ลิงก์กับระดับการเข้าถึงขององค์ประกอบในวิวพอร์ต คุณสร้างได้โดยใช้ฟังก์ชัน
view()แล้วนำไปใช้กับภาพเคลื่อนไหวโดยใช้พร็อพเพอร์ตี้animation-timeline.animated-element { animation-timeline: view(); }โดยค่าเริ่มต้น
view()จะติดตามองค์ประกอบบนแกนblockหากต้องการติดตามบนแกนinlineคุณสามารถใช้view(inline)ได้จำกัดภาพเคลื่อนไหวให้อยู่ในช่วง
entryและexitพร็อพเพอร์ตี้animation-rangeช่วยให้คุณระบุส่วนของไทม์ไลน์ที่ภาพเคลื่อนไหวควรทำงานได้- ช่วง
entryจะครอบคลุมเวลาตั้งแต่ที่องค์ประกอบเข้าสู่วิวพอร์ตเป็นครั้งแรกจนกระทั่งมองเห็นได้ทั้งหมด - ช่วง
exitครอบคลุมเวลาตั้งแต่ที่องค์ประกอบเริ่มออกจากวิวพอร์ตจนกระทั่งซ่อนโดยสมบูรณ์
.animated-element { animation-range: entry, exit; }- ช่วง
โค้ดตัวอย่าง
โค้ดนี้จะทำให้องค์ประกอบย่อยโดยตรงของตัวเลื่อนเคลื่อนไหวเมื่อเลื่อนโดยใช้ view-timeline แบบไม่ระบุชื่อ
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: view(inline);
animation-range: entry, exit;
}
}
}
เมื่อองค์ประกอบเข้าสู่พอร์ตการเลื่อน ระบบจะเล่นภาพเคลื่อนไหว grow และเมื่อองค์ประกอบออกจากพอร์ตการเลื่อน ระบบจะเล่นภาพเคลื่อนไหว shrink
โค้ดต่อไปนี้มีผลลัพธ์ภาพเหมือนกัน แต่จะทำให้องค์ประกอบย่อยโดยตรงของตัวเลื่อนเคลื่อนไหวเมื่อเลื่อนโดยใช้ view-timeline ที่มีชื่อ
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
view-timeline: --tl inline;
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: --tl;
animation-range: entry, exit;
}
}
}
แนวทางปฏิบัติแนะนำ
เมื่อใช้ภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน คุณควรทำตามแนวทางปฏิบัติแนะนำต่อไปนี้เพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ราบรื่นและเข้าถึงได้
- ควรรวมการตรวจหาฟีเจอร์: เบราว์เซอร์บางรายการไม่รองรับภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน ใช้
@supports ((animation-timeline: view()) and (animation-range: entry))เพื่อตรวจสอบการรองรับและระบุเบราว์เซอร์สำรองสำหรับเบราว์เซอร์ที่ไม่รองรับ- ต้องรวมการตรวจสอบ
(animation-range: entry)ไว้ที่นี่เพื่อกรองเบราว์เซอร์ที่รองรับเพียงบางส่วนออก - อย่าใช้แพ็กเกจ
scroll-timeline-polyfillสำหรับกลยุทธ์สำรอง เนื่องจากฟีเจอร์ยังไม่สมบูรณ์และมีปัญหาที่ทราบอยู่แล้วจำนวนมาก - หากภาพเคลื่อนไหวถือเป็นเพียงการตกแต่ง ให้เลือกใช้การเพิ่มประสิทธิภาพแบบต่อเนื่อง และอย่าระบุทางเลือกสำรอง
- ต้องรวมการตรวจสอบ
- ควรเคารพค่ากำหนดของผู้ใช้: ผู้ใช้บางรายต้องการให้มีการเคลื่อนไหวน้อยลงบนเว็บ ใช้คิวรีสื่อ
prefers-reduced-motionเพื่อปิดใช้หรือลดภาพเคลื่อนไหวสำหรับผู้ใช้เหล่านี้ - ควรพยายามทำให้เฉพาะพร็อพเพอร์ตี้ CSS ที่มีประสิทธิภาพเคลื่อนไหว: เพื่อให้ภาพเคลื่อนไหวราบรื่นที่สุด ให้ใช้พร็อพเพอร์ตี้ที่เคลื่อนไหวซึ่งจัดการได้โดยเทรด Compositor ของเบราว์เซอร์ เช่น
transformและopacityการทำให้พร็อพเพอร์ตี้อื่นๆ เช่นwidthหรือheightเคลื่อนไหวอาจทำให้เกิดปัญหาด้านประสิทธิภาพ - ควรใช้ลำดับการประกาศที่ถูกต้อง: เมื่อใช้พร็อพเพอร์ตี้ชวเลข
animationให้ประกาศanimation-timelineหลังจากพร็อพเพอร์ตี้ดังกล่าวเพื่อป้องกันไม่ให้ชวเลขรีเซ็ตไทม์ไลน์
เมื่อใช้ฟังก์ชัน view() เพื่อสร้างภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน ให้ทำดังนี้
- ไม่บังคับ ระบุแกนที่จะติดตามอย่างชัดเจน: เมื่อไม่ได้กำหนดเป้าหมายแกน
blockเริ่มต้น (เช่น ในแถบเลื่อนแนวนอน) ให้ระบุแกนที่จะติดตามอย่างชัดเจนด้วยview(block)หรือview(inline) - เมื่อไม่ได้ใช้ภาพเคลื่อนไหวกับวัตถุที่ติดตาม ให้ใช้ไทม์ไลน์มุมมองที่มีชื่อ
เมื่อใช้พร็อพเพอร์ตี้ view-timeline เพื่อสร้างภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน ให้ทำดังนี้
- ควรใช้ CSS
<dashed-ident>สำหรับชื่อ - ไม่บังคับ ระบุแกนที่จะติดตามอย่างชัดเจน: เมื่อไม่ได้กำหนดเป้าหมายแกน
blockเริ่มต้น (เช่น ในแถบเลื่อนแนวนอน) ให้ระบุแกนที่จะติดตามด้วยview-timeline-axisอย่างชัดเจน - ควรตรวจสอบว่าขอบเขตของการค้นหาใช้งานได้: เมื่อองค์ประกอบที่ประกาศ
view-timelineไม่ใช่ระดับบนสุดแบบ Flat Tree ขององค์ประกอบที่เคลื่อนไหว ให้เพิ่มระดับการมองเห็นชื่อของview-timelineโดยใช้timeline-scopeในระดับบนสุดที่ใช้ร่วมกัน
ใช้ view-timeline ที่มีชื่อเมื่อองค์ประกอบหลายรายการหรือองค์ประกอบย่อยของเรื่องที่ติดตามต้องเคลื่อนไหว
การรองรับเบราว์เซอร์และกลยุทธ์สำรอง
ดังนั้น โดยทั่วไปจึงต้องมีกลยุทธ์สำรอง
สำหรับเบราว์เซอร์ที่ไม่รองรับภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน คุณสามารถใช้โหมดสำรองเพื่อสร้างเอฟเฟกต์ภาพขึ้นมาใหม่ได้ โดยปกติแล้ว ฟังก์ชันสำรองจะสร้างขึ้นด้วย Listener การเลื่อน (สำหรับเอฟเฟกต์ ScrollTimeline) หรือ IntersectionObserver API (สำหรับเอฟเฟกต์ ViewTimeline)
ในเบราว์เซอร์ที่มีการรองรับภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อนในตัว ให้ใช้การติดตั้งใช้งาน CSS แบบเนทีฟเสมอ เนื่องจากมีประสิทธิภาพมากกว่า
โปรดทราบว่าคุณไม่สามารถสร้างเอฟเฟกต์ทั้งหมดขึ้นมาใหม่ได้โดยใช้วิธีการสำรอง
สำหรับ Use Case นี้โดยเฉพาะ สคริปต์ต่อไปนี้จะใช้โหมดสำรองสำหรับเบราว์เซอร์ที่ไม่รองรับภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน โดยใช้ IntersectionObserver เพื่อติดตามระดับการมองเห็นขององค์ประกอบ .wrapper และอัปเดตพร็อพเพอร์ตี้ transform ของเลเยอร์ตามตำแหน่งการเลื่อน
<script>
if (!CSS.supports('(animation-timeline: view()) and (animation-range: entry)')) {
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
// This matches the effect as defined in the CSS example above.
// Customize this further if needed.
entry.target.style.scale = 0.5 + entry.intersectionRatio * 0.5;
}
},
{
threshold: Array.from({ length: 101 }, (_, i) => i / 100),
}
);
document.querySelectorAll('.scroller > *').forEach((el) => {
observer.observe(el);
});
}
</script>