สร้างประสบการณ์การเลื่อนที่ควบคุมได้ดีด้วยการประกาศตำแหน่งการเลื่อน
ฟีเจอร์ CSS Scroll Snap ช่วยให้นักพัฒนาเว็บสร้างประสบการณ์การเลื่อนที่ควบคุมได้ดีด้วยการประกาศตำแหน่งการหยุด Scroll บทความแบบแบ่งหน้าและภาพสไลด์เป็นตัวอย่าง 2 ตัวอย่างที่พบได้ทั่วไป CSS Scroll Snap มี API ที่ใช้งานง่ายและสอดคล้องกันสำหรับการสร้างรูปแบบ UX ที่ได้รับความนิยมเหล่านี้
ข้อมูลเบื้องต้น
กรณีสําหรับการเลื่อนแบบ Snap
การเลื่อนเป็นวิธีที่ได้รับความนิยมและเป็นธรรมชาติในการโต้ตอบกับเนื้อหาบนเว็บ ซึ่งเป็นวิธีดั้งเดิมของแพลตฟอร์มในการให้สิทธิ์เข้าถึงข้อมูลมากกว่าที่แสดงบนหน้าจอพร้อมกัน ซึ่งจะมีประโยชน์อย่างยิ่งในแพลตฟอร์มอุปกรณ์เคลื่อนที่ที่มีพื้นที่หน้าจอจํากัด จึงไม่น่าแปลกใจที่ผู้เขียนเว็บจำนวนมากขึ้นเลือกจัดระเบียบเนื้อหาเป็นรายการแบบแบนที่เลื่อนได้แทนการจัดระเบียบแบบลําดับชั้นที่ลึก
ข้อเสียหลักของการเลื่อนคือความแม่นยำ แทบจะไม่มีกรณีที่การเลื่อนจะสิ้นสุดลงโดยที่บรรทัดนั้นอยู่ตรงกับย่อหน้าหรือประโยค ปัญหานี้เห็นได้ชัดยิ่งขึ้นสำหรับเนื้อหาแบบแบ่งหน้าหรือเนื้อหาแบบรายการที่มีขอบเขตที่มีความหมายเมื่อการเลื่อนสิ้นสุดลงตรงกลางหน้าหรือรูปภาพ ทำให้มองเห็นเนื้อหาบางส่วน กรณีการใช้งานเหล่านี้จะได้รับประโยชน์จากประสบการณ์การเลื่อนที่ควบคุมได้ดี
นักพัฒนาเว็บใช้โซลูชัน JavaScript ในการควบคุมการเลื่อนมานานแล้วเพื่อแก้ปัญหานี้ อย่างไรก็ตาม โซลูชันที่ใช้ JavaScript ไม่สามารถให้โซลูชันที่ตรงตามต้นฉบับได้เนื่องจากไม่มีองค์ประกอบพื้นฐานในการปรับแต่งการเลื่อนหรือเข้าถึงการเลื่อนแบบคอมโพสิต CSS Scroll Snap ช่วยให้คุณมีโซลูชันที่รวดเร็ว เที่ยงตรงสูง และใช้งานง่าย ซึ่งทํางานอย่างสม่ำเสมอในเบราว์เซอร์ต่างๆ
การหยุดการเลื่อน CSS ช่วยให้ผู้เขียนเว็บทำเครื่องหมายขอบเขตของคอนเทนเนอร์การเลื่อนแต่ละรายการสำหรับการดำเนินการเลื่อนที่จะสิ้นสุด จากนั้นเบราว์เซอร์จะเลือกตำแหน่งสิ้นสุดที่เหมาะสมที่สุดโดยขึ้นอยู่กับรายละเอียดของการดำเนินการเลื่อน เลย์เอาต์และระดับการมองเห็นของคอนเทนเนอร์การเลื่อน และรายละเอียดของตำแหน่งการหยุด กลับไปที่ตัวอย่างก่อนหน้านี้ เมื่อผู้ใช้เลื่อนภาพสไลด์จนจบแล้ว ภาพที่เห็นจะปรากฏขึ้น JavaScript ไม่ต้องทำการปรับเปลี่ยนการเลื่อน
CSS Scroll Snap
การหยุดการเลื่อนคือการปรับออฟเซ็ตการเลื่อนของคอนเทนเนอร์การเลื่อนให้อยู่ในตำแหน่งหยุดที่ต้องการเมื่อการเลื่อนเสร็จสิ้น
คุณอาจเลือกให้คอนเทนเนอร์การเลื่อนใช้การเลื่อนไปยังจุดที่พอดีโดยใช้พร็อพเพอร์ตี้ scroll-snap-type
ซึ่งบอกให้เบราว์เซอร์พิจารณาจัดวางคอนเทนเนอร์การเลื่อนนี้ไปยังตำแหน่งที่แสดงผลโดยรายการที่สืบทอด scroll-snap-type
กำหนดแกนที่จะเลื่อน: x
, y
หรือ both
และระดับความเข้มงวดของการยึดตำแหน่ง: mandatory
, proximity
เราจะอธิบายเพิ่มเติมในภายหลัง
คุณสามารถระบุตำแหน่งการยึดได้โดยประกาศการจัดตำแหน่งที่ต้องการในองค์ประกอบ
ตำแหน่งนี้คือระยะการเลื่อนที่คอนเทนเนอร์การเลื่อนของบรรพบุรุษที่อยู่ใกล้ที่สุดและองค์ประกอบนั้นจัดแนวตามที่กำหนดไว้สำหรับแกนนั้นๆ การจัดแนวต่อไปนี้เป็นไปได้ในแต่ละแกน start
, end
, center
การจัดแนว start
หมายความว่าขอบเริ่มต้นของ Snapport ของคอนเทนเนอร์การเลื่อนควรอยู่ตรงกับขอบเริ่มต้นของพื้นที่ Snap ขององค์ประกอบ ในทํานองเดียวกัน การปรับแนว end
และ center
หมายความว่าขอบหรือกึ่งกลางของปลายพอร์ตการจับคู่ของคอนเทนเนอร์การเลื่อนควรอยู่ตรงกับขอบหรือกึ่งกลางของปลายพื้นที่การจับคู่ขององค์ประกอบ
ตัวอย่างต่อไปนี้แสดงวิธีใช้แนวคิดเหล่านี้
ตัวอย่าง: แกลเลอรีแนวนอน
กรณีการใช้งานที่พบบ่อยของภาพสไลด์แบบเลื่อนคือภาพสไลด์ ตัวอย่างเช่น หากต้องการสร้างภาพสไลด์แนวนอนที่แสดงรูปภาพแต่ละรูปเมื่อคุณเลื่อน เราอาจระบุคอนเทนเนอร์การเลื่อนให้มี scroll-snap-type
บนแกนแนวนอนเป็นค่าบังคับ และตั้งค่ารูปภาพแต่ละรูปเป็น scroll-snap-align: center
เพื่อให้การจับภาพจัดวางรูปภาพในภาพสไลด์ให้อยู่ตรงกลาง
#gallery {
scroll-snap-type: x mandatory;
overflow-x: scroll;
display: flex;
}
#gallery img {
scroll-snap-align: center;
}
<div id="gallery">
<img src="cat.jpg">
<img src="dog.jpg">
<img src="another_cute_animal.jpg">
</div>
เนื่องจากตำแหน่งการยึดจะเชื่อมโยงกับองค์ประกอบ อัลกอริทึมการยึดจึงสามารถทำงานได้อย่างชาญฉลาดเกี่ยวกับเวลาและวิธียึดเมื่อพิจารณาจากองค์ประกอบและขนาดของคอนเทนเนอร์การเลื่อน ตัวอย่างเช่น พิจารณากรณีที่รูปภาพหนึ่งมีขนาดใหญ่กว่าภาพสไลด์ อัลกอริทึมการจับคู่ที่โง่เง่าอาจทำให้ผู้ใช้เลื่อนดูภาพเพื่อดูภาพเต็มไม่ได้ แต่ข้อกําหนดกําหนดให้การใช้งานต้องตรวจหากรณีนี้และอนุญาตให้ผู้ใช้เลื่อนไปรอบๆ ในรูปภาพนั้นได้อย่างอิสระโดยยึดเฉพาะที่ขอบ
ตัวอย่าง: หน้าผลิตภัณฑ์ตามเส้นทาง
กรณีทั่วไปอีกอย่างหนึ่งที่อาจได้รับประโยชน์จากการหยุดการปัดคือหน้าเว็บที่มีส่วนต่างๆ ที่สอดคล้องกันหลายส่วนให้เลื่อนขึ้นลง เช่น หน้าผลิตภัณฑ์ทั่วไป scroll-snap-type: y proximity;
เหมาะกว่าสําหรับกรณีเช่นนี้ ฟีเจอร์นี้จะไม่รบกวนเมื่อผู้ใช้เลื่อนไปที่ตรงกลางของส่วนใดส่วนหนึ่ง แต่ยังช่วยดึงดูดความสนใจไปยังส่วนใหม่เมื่อผู้ใช้เลื่อนเข้าไปใกล้พอ
โดยวิธีดำเนินการมีดังนี้
article {
scroll-snap-type: y proximity;
/* Reserve space for header plus some extra space for sneak peeking. */
scroll-padding-top: 15vh;
overflow-y: scroll;
}
section {
/* Snap align start. */
scroll-snap-align: start;
}
header {
position: fixed;
height: 10vh;
}
<article>
<header> Header </header>
<section> Section One </section>
<section> Section Two </section>
<section> Section Three </section>
</article>
ระยะห่างจากขอบและระยะขอบของแถบเลื่อน
หน้าผลิตภัณฑ์มีส่วนหัวด้านบนที่ตำแหน่งคงที่ การออกแบบยังกำหนดให้ส่วนบนบางส่วนยังคงมองเห็นได้เมื่อคอนเทนเนอร์การเลื่อนถูกจัดตำแหน่งเพื่อใช้เป็นตัวช่วยในการออกแบบสำหรับผู้ใช้เกี่ยวกับเนื้อหาด้านบน
พร็อพเพอร์ตี้ scroll-padding
เป็นพร็อพเพอร์ตี้ CSS ใหม่ที่สามารถใช้เพื่อปรับพื้นที่ที่มองเห็นได้จริงของคอนเทนเนอร์การเลื่อนหรือ Snapport ซึ่งจะใช้เมื่อคำนวณการจัดแนวการเลื่อน พร็อพเพอร์ตี้นี้กำหนดการฝังเมื่อเทียบกับกล่องระยะห่างจากขอบของคอนเทนเนอร์การเลื่อน ในตัวอย่างของเรา เราได้เพิ่ม15vh
การฝังเพิ่มเติม15vh
ที่ด้านบน ซึ่งจะบอกให้เบราว์เซอร์พิจารณาตำแหน่งที่ต่ำกว่า นั่นคือ15vh
ใต้ขอบด้านบนของคอนเทนเนอร์การเลื่อน เพื่อเป็นขอบเริ่มต้นแนวตั้งสำหรับการเลื่อน เมื่อใช้การยึด ขอบเริ่มต้นขององค์ประกอบเป้าหมายการยึดจะชิดกับตำแหน่งใหม่นี้ จึงทำให้มีที่ว่างด้านบน
พร็อพเพอร์ตี้ scroll-margin
กำหนดจำนวนการเริ่มต้นที่ใช้เพื่อปรับกล่องที่มีประสิทธิภาพของเป้าหมายการยึด ซึ่งคล้ายกับวิธีที่ scroll-padding
ทำงานในคอนเทนเนอร์การเลื่อนการยึด
คุณอาจสังเกตเห็นว่าพร็อพเพอร์ตี้ทั้ง 2 รายการนี้ไม่มีคําว่า "snap
" การดำเนินการนี้เกิดขึ้นโดยเจตนา เนื่องจากมีการแก้ไขกล่องสําหรับการดำเนินการเลื่อนที่เกี่ยวข้องทั้งหมด ไม่ใช่แค่การเลื่อนไปยังส่วนที่ต้องการ เช่น Chrome จะพิจารณาค่าเหล่านี้เมื่อคำนวณขนาดหน้าเว็บสําหรับการเลื่อนหน้า เช่น PageDown และ PageUp รวมถึงเมื่อคํานวณจํานวนการเลื่อนสําหรับการดําเนินการElement.scrollIntoView()
การโต้ตอบกับ API เลื่อนอื่นๆ
DOM Scrolling API
การเลื่อนแบบกระโดดจะเกิดขึ้นหลังจากการดำเนินการเลื่อนทั้งหมด รวมถึงการดำเนินการที่เริ่มต้นโดยสคริปต์ เมื่อคุณใช้ API เช่น Element.scrollTo
เบราว์เซอร์จะคำนวณตำแหน่งการเลื่อนที่ต้องการของการดำเนินการ จากนั้นจะใช้ตรรกะการยึดที่เหมาะสมเพื่อค้นหาตำแหน่งสุดท้ายที่ยึด ดังนั้น สคริปต์ของผู้ใช้จึงไม่จำเป็นต้องทำการคำนวณใดๆ สำหรับการจับคู่
การเลื่อนอย่างราบรื่น
การเลื่อนอย่างราบรื่นจะควบคุมลักษณะการทํางานของการเลื่อนแบบเป็นโปรแกรม ขณะที่การเลื่อนไปยังส่วนที่ต้องการจะกําหนดปลายทาง เนื่องจากตัวควบคุมเหล่านี้ควบคุมการเลื่อนในแนวตั้งและแนวนอน จึงใช้ร่วมกันและเสริมกันได้
ลักษณะการเลื่อนเกิน
Overscroll behavior API จะควบคุมวิธีเชื่อมโยงการเลื่อนในองค์ประกอบหลายรายการ และจะไม่ได้รับผลกระทบจากการเลื่อนแบบ Snap
ข้อควรระวังและแนวทางปฏิบัติแนะนำ
หลีกเลี่ยงการใช้การจับคู่แบบบังคับเมื่อองค์ประกอบเป้าหมายอยู่ห่างกันมาก ซึ่งอาจทำให้เข้าถึงเนื้อหาที่อยู่ตรงกลางตำแหน่งการจับคู่ไม่ได้
ในหลายกรณี คุณสามารถเพิ่มการเลื่อนไปยังส่วนถัดไปเพื่อเพิ่มประสิทธิภาพได้โดยไม่ต้องตรวจหาองค์ประกอบ
หากจำเป็น ให้ใช้ @supports
หรือ CSS.supports
เพื่อตรวจหาการรองรับ CSS Scroll Snap
หลีกเลี่ยงการใช้ scroll-snap-type
ซึ่งอยู่ในข้อกำหนดที่เลิกใช้งานแล้วด้วย
การตรวจหาฟีเจอร์ใน CSS
@supports (scroll-snap-align: start) {
article {
scroll-snap-type: y proximity;
scroll-padding-top: 15vh;
overflow-y: scroll;
}
}
การตรวจหาฟีเจอร์ใน JavaScript
if (CSS.supports('scroll-snap-align: start')) {
// use css scroll snap
} else {
// use fallback
}
อย่าคิดว่า API เลื่อนแบบเป็นโปรแกรม เช่น Element.scrollTo
จะสิ้นสุดที่ออฟเซตการเลื่อนที่ขอเสมอ การเลื่อนแบบกระโดดอาจปรับค่าออฟเซตการเลื่อนหลังจากการเลื่อนแบบเป็นโปรแกรมเสร็จสมบูรณ์ โปรดทราบว่านี่ไม่ใช่สมมติฐานที่ดีแม้แต่ก่อนที่จะมีการเลื่อนแบบ Snap เนื่องจากการเลื่อนอาจถูกขัดจังหวะด้วยเหตุผลอื่นๆ แต่กรณีนี้จะเกิดขึ้นกับการเลื่อนแบบ Snap โดยเฉพาะ
งานในอนาคต
ประสบการณ์การเลื่อนเป็นประเด็นหลักในแบบสํารวจล่าสุดของทีม Chrome
ผลการสำรวจระบุถึงหลายด้านที่ต้องดำเนินการเพิ่มเติมเพื่อลดช่องว่างระหว่างไลบรารีปลั๊กอินกับ CSS
งานที่กําลังจะมีขึ้นจะมุ่งเน้นที่ scroll-snap
ซึ่งรวมถึง
- ความพร้อมใช้งานและความเข้ากันได้ของ API ในเบราว์เซอร์ต่างๆ
- พัฒนาCSS API ใหม่ เช่น
scroll-start
- ทํางานกับเหตุการณ์ JS ใหม่ เช่น
snapChanged()