จัดการการเลื่อนแบบแม่เหล็ก การเปลี่ยนสถานะที่เบราว์เซอร์ทำแอนิเมชันให้ และการเคารพ prefers-reduced-motion อย่างเคร่งครัด
เปิดบทเรียนนี้ใน Kodokonscroll snap เกี่ยวข้องกับผู้เล่นสองฝ่าย: คอนเทนเนอร์เป็นตัวกำหนด snapport (พื้นที่ที่มองเห็นได้ ซึ่งถูกหดด้วย scroll-padding) และกลยุทธ์ผ่าน scroll-snap-type โดย proximity จะสแนปเฉพาะเมื่อใกล้จุดสแนปเท่านั้น ในขณะที่ mandatory รับประกันว่าคุณจะไปหยุดที่จุดสแนปเสมอ แม้กระทั่งหลังจากการเลื่อนด้วยโปรแกรม ส่วนลูก ๆ เป็นตัวประกาศพื้นที่การจัดแนวของมันด้วย scroll-snap-align (ปรับได้ผ่าน scroll-margin) มีรายละเอียดปลีกย่อยที่ไม่ค่อยมีใครรู้: ระหว่างการปัดเร็ว ๆ เบราว์เซอร์อาจ ข้ามจุดสแนปหลายจุด ได้อย่างชอบธรรม scroll-snap-stop: always จะบังคับให้มันหยุดที่แต่ละจุด ซึ่งจำเป็นสำหรับคารูเซลแบบสตอรี
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-padding-inline: 1rem;
}
.carousel > article {
flex: 0 0 80%;
scroll-snap-align: center;
scroll-snap-stop: always;
}View Transitions API ทำแอนิเมชันการเปลี่ยนสถานะของ DOM ได้โดยไม่ต้องใช้ไลบรารีใด ๆ document.startViewTransition(callback) จะจับ ภาพสแนปช็อตเชิงภาพ ของสถานะปัจจุบัน รัน callback ของคุณ (ซึ่งเปลี่ยนแปลง DOM) แล้วจึงทำแอนิเมชันระหว่างสถานะเก่าและใหม่ เบื้องหลังนั้น เบราว์เซอร์จะสร้างต้นไม้ของ pseudo-element ทับอยู่บนหน้าเว็บ: ::view-transition บรรจุเอลิเมนต์ ::view-transition-group ซึ่งแต่ละตัวมี ::view-transition-old (ภาพสแนปช็อต เนื้อหาที่ถูกแทนที่ซึ่งเทียบได้กับรูปภาพ) และ ::view-transition-new (ตัวแทนที่มีชีวิตอยู่) ค่าเริ่มต้นคือ: การเฟดแบบไขว้ (cross-fade) หน้าเว็บจะ ไม่สามารถโต้ตอบได้ ระหว่างการเปลี่ยนผ่าน
function applyUpdate(updateDom) {
if (!document.startViewTransition) {
updateDom();
return;
}
document.startViewTransition(() => updateDom());
}พลังที่แท้จริงมาจาก view-transition-name: เอลิเมนต์ที่ถูกตั้งชื่อจะถูกดึงออกไปยัง กลุ่มการเปลี่ยนผ่านของตัวเอง หากมีเอลิเมนต์ที่มีชื่อเดียวกันอยู่ทั้งก่อนและหลัง เบราว์เซอร์จะประมาณค่าตำแหน่งและขนาดระหว่างทั้งสองให้โดยอัตโนมัติ นั่นคือเอฟเฟกต์มอร์ฟจากรูปย่อไปสู่มุมมองแบบเต็มหน้าจอ โดยไม่ต้องเขียนโค้ดแอนิเมชัน JavaScript แม้แต่บรรทัดเดียว แต่ละชื่อต้อง ไม่ซ้ำกัน บนหน้าเว็บ ณ ช่วงเวลาใดเวลาหนึ่ง มิเช่นนั้นการเปลี่ยนผ่านจะถูกยกเลิก pseudo-element เหล่านี้ถูกจัดสไตล์ด้วยแอนิเมชัน CSS ธรรมดา
.hero-thumb { view-transition-name: hero; }
::view-transition-old(hero),
::view-transition-new(hero) {
animation-duration: 0.4s;
animation-timing-function: ease-in-out;
}สิ่งที่เหลืออยู่คือข้อผูกพันด้านการเข้าถึง: prefers-reduced-motion: reduce เป็นสัญญาณบ่งบอกถึงผู้ใช้ที่ไวต่อการเคลื่อนไหว (ความผิดปกติของระบบทรงตัว หรืออาการไมเกรน) การลดไม่ได้หมายถึงการเอาออก: การเฟดด้วย opacity ยังคงยอมรับได้ สิ่งที่ต้องทำให้เป็นกลางคือการเคลื่อนไหวขนาดใหญ่ การซูม และเอฟเฟกต์พารัลแลกซ์ต่างหาก คุณรู้จักการเขียนทับแบบรวมเชิงป้องกันใน CSS อยู่แล้ว (ระยะเวลาเกือบเป็นศูนย์ ครอบคลุมในโมดูลก่อนหน้า) view transitions เพิ่มแนวรบที่สอง: ในฝั่ง JavaScript ให้สอบถาม window.matchMedia("(prefers-reduced-motion: reduce)") ก่อนเริ่มการเปลี่ยนผ่านหรือการเลื่อนแบบมีแอนิเมชัน
const reduceMotion = window.matchMedia(
'(prefers-reduced-motion: reduce)'
).matches;
if (reduceMotion || !document.startViewTransition) {
updateDom();
} else {
document.startViewTransition(() => updateDom());
}