สร้างประสบการณ์การเลื่อนที่มีการควบคุมอย่างดีโดยการประกาศตำแหน่งการเลื่อน
ฟีเจอร์ CSS Scroll Snap ช่วยให้นักพัฒนาเว็บสร้างประสบการณ์การเลื่อนที่ควบคุมได้ดีโดยการประกาศตำแหน่งการเลื่อน บทความแบบแบ่งหน้าและภาพสไลด์เป็นตัวอย่างที่ใช้กันโดยทั่วไป ของรูปแบบนี้ CSS Scroll Snap มี API ที่ใช้งานง่ายและสอดคล้องกันสำหรับ สร้างรูปแบบ UX ยอดนิยมเหล่านี้
ฉากหลัง
กรณีที่ต้องใช้การเลื่อนแบบสแนป
การเลื่อนเป็นวิธีที่ได้รับความนิยมและเป็นธรรมชาติในการโต้ตอบกับเนื้อหาบนเว็บ ซึ่งเป็นวิธีดั้งเดิมของแพลตฟอร์มในการให้สิทธิ์เข้าถึงข้อมูลเพิ่มเติมที่มองเห็นบนหน้าจอได้ในครั้งเดียว และมีความสำคัญอย่างยิ่งบนแพลตฟอร์มอุปกรณ์เคลื่อนที่ที่มีพื้นที่หน้าจอจำกัด จึงไม่น่าแปลกใจที่ผู้เขียนเว็บ จะชอบจัดระเบียบเนื้อหาเป็นรายการแบบเลื่อนได้มากกว่า ลำดับชั้นที่ซับซ้อน
ข้อเสียหลักของการเลื่อนคือความไม่แม่นยำ การเลื่อนมักไม่สิ้นสุด ที่ย่อหน้าหรือประโยค ซึ่งจะเห็นได้ชัดเจนยิ่งขึ้นสำหรับเนื้อหาที่มีการแบ่งหน้า หรือเนื้อหาที่จัดเป็นรายการซึ่งมีขอบเขตที่ชัดเจน เมื่อการเลื่อนสิ้นสุดที่ กึ่งกลางของหน้าหรือรูปภาพ ทำให้มองเห็นได้เพียงบางส่วน กรณีการใช้งานเหล่านี้ ได้รับประโยชน์จากประสบการณ์การเลื่อนที่ควบคุมได้ดี
นักพัฒนาเว็บใช้โซลูชันที่ใช้ JavaScript เพื่อควบคุม การเลื่อนมานานแล้วเพื่อช่วยแก้ไขข้อบกพร่องนี้ อย่างไรก็ตาม โซลูชันที่ใช้ JavaScript ไม่สามารถให้โซลูชันที่มีความเที่ยงตรงสมบูรณ์เนื่องจากไม่มีองค์ประกอบพื้นฐานสำหรับการปรับแต่งการเลื่อน หรือการเข้าถึงการเลื่อนแบบคอมโพสิต CSS Scroll Snap ช่วยให้มั่นใจได้ว่าโซลูชันที่รวดเร็ว มีความเที่ยงตรงสูง และใช้งานง่ายจะทำงาน ได้อย่างสอดคล้องกันในเบราว์เซอร์ต่างๆ
CSS Scroll Snap ช่วยให้ผู้เขียนเว็บสามารถทำเครื่องหมายคอนเทนเนอร์การเลื่อนแต่ละรายการด้วยขอบเขต สำหรับการดำเนินการเลื่อนที่จะสิ้นสุด จากนั้นเบราว์เซอร์จะเลือกตำแหน่งสิ้นสุดที่เหมาะสมที่สุดตามรายละเอียดของการดำเนินการเลื่อน เลย์เอาต์และความสามารถในการมองเห็นของคอนเทนเนอร์เลื่อน และรายละเอียดของตำแหน่งสแนป แล้วเคลื่อนไหวไปยังตำแหน่งนั้นอย่างราบรื่น กลับไปที่ตัวอย่างก่อนหน้านี้ เมื่อผู้ใช้เลื่อนภาพสไลด์จนสุด รูปภาพที่มองเห็นจะเลื่อนเข้าที่ JavaScript ไม่จำเป็นต้องปรับการเลื่อน

CSS Scroll Snap
การเลื่อนแบบสแนปคือการปรับออฟเซ็ตการเลื่อนของคอนเทนเนอร์ที่เลื่อนได้ ให้อยู่ที่ตำแหน่งสแนปที่ต้องการเมื่อการดำเนินการเลื่อนเสร็จสิ้น
คุณเลือกใช้การเลื่อนแบบสแนปในคอนเทนเนอร์ที่เลื่อนได้โดยใช้พร็อพเพอร์ตี้
scroll-snap-type
ซึ่งจะบอกเบราว์เซอร์ว่าควรพิจารณาการสแนปคอนเทนเนอร์เลื่อนนี้ไปยังตำแหน่งสแนปที่สร้างโดยองค์ประกอบย่อย scroll-snap-type
กำหนดแกนที่การเลื่อนเกิดขึ้น: x
, y
หรือ both
และ
ความเข้มงวดในการสแนป: mandatory
, proximity
เราจะพูดถึงเรื่องนี้เพิ่มเติมในภายหลัง
คุณสร้างตำแหน่งสแนปได้โดยประกาศการจัดแนวที่ต้องการในองค์ประกอบ
ตำแหน่งนี้คือออฟเซ็ตการเลื่อนที่คอนเทนเนอร์การเลื่อนของบรรพบุรุษที่ใกล้ที่สุดและองค์ประกอบจะได้รับการจัดแนวตามที่ระบุไว้สำหรับแกนที่กำหนด การจัดแนวต่อไปนี้เป็นไปได้ในแต่ละแกน: start
, end
, center
การจัดแนว start
หมายความว่าขอบเริ่มต้นของ Snapport ของคอนเทนเนอร์เลื่อนควร
ตรงกับขอบเริ่มต้นของพื้นที่สแนปขององค์ประกอบ ในทำนองเดียวกัน การจัดแนว end
และ
center
หมายความว่าขอบสิ้นสุดหรือกึ่งกลางของ Snapport ของคอนเทนเนอร์เลื่อน
ควรอยู่ในแนวเดียวกับขอบสิ้นสุดหรือกึ่งกลางของพื้นที่สแนปขององค์ประกอบ
ตัวอย่างต่อไปนี้จะแสดงวิธีใช้แนวคิดเหล่านี้
ตัวอย่าง: แกลเลอรีแนวนอน
กรณีการใช้งานทั่วไปสำหรับการเลื่อนแบบสแนปคือภาพสไลด์ เช่น หากต้องการสร้างภาพสไลด์แนวนอนที่เลื่อนไปแต่ละรูปภาพเมื่อคุณเลื่อน เราสามารถระบุคอนเทนเนอร์การเลื่อนให้มี 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>
เนื่องจากตำแหน่งสแนปเชื่อมโยงกับองค์ประกอบ อัลกอริทึมการสแนป จึงสามารถพิจารณาได้อย่างชาญฉลาดว่าเมื่อใดและอย่างไรที่จะสแนปองค์ประกอบและขนาดคอนเทนเนอร์เลื่อน เช่น พิจารณากรณีที่รูปภาพ 1 รูปมีขนาดใหญ่กว่า ภาพสไลด์ อัลกอริทึมการสแนปแบบง่ายอาจทำให้ผู้ใช้เลื่อนไปรอบๆ เพื่อดูรูปภาพแบบเต็มไม่ได้ แต่ข้อกำหนด กำหนดให้การติดตั้งใช้งานต้องตรวจหาเคสนี้และอนุญาตให้ผู้ใช้เลื่อนได้อย่างอิสระ ภายในรูปภาพนั้นโดยจะสแนปที่ขอบเท่านั้น
ตัวอย่าง: หน้าผลิตภัณฑ์ที่มีเส้นทางการเข้าชม
อีกกรณีการใช้งานทั่วไปที่การเลื่อนแบบสแนปมีประโยชน์คือหน้าเว็บที่มี
หลายส่วนเชิงตรรกะให้เลื่อนในแนวตั้ง เช่น หน้าผลิตภัณฑ์ทั่วไป 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
ใต้ขอบด้านบนของคอนเทนเนอร์เลื่อน เป็นขอบเริ่มต้นแนวตั้งสำหรับการ
เลื่อนสแนป เมื่อสแนป ขอบเริ่มต้นขององค์ประกอบเป้าหมายการสแนปจะ
อยู่ในแนวเดียวกับตำแหน่งใหม่นี้ จึงเหลือพื้นที่ด้านบน
พร็อพเพอร์ตี้ scroll-margin
กำหนดจำนวนเริ่มต้นที่ใช้เพื่อปรับกล่องเป้าหมายการสแนป
ที่มีผลคล้ายกับวิธีที่ฟังก์ชัน scroll-padding
ทำงานในคอนเทนเนอร์
การเลื่อนแบบสแนป
คุณอาจสังเกตเห็นว่าพร็อพเพอร์ตี้ทั้ง 2 รายการนี้ไม่มีคำว่า "snap
" อยู่
การทำงานนี้เป็นไปตามที่ตั้งใจไว้ เนื่องจากปุ่มเหล่านี้จะแก้ไขกล่องสำหรับการดำเนินการเลื่อนที่เกี่ยวข้องทั้งหมดจริงๆ ไม่ใช่แค่การเลื่อนแบบสแนป เช่น Chrome จะนำ
องค์ประกอบเหล่านี้มาพิจารณาเมื่อคำนวณขนาดหน้าเว็บสำหรับการดำเนินการเลื่อนแบบแบ่งหน้า เช่น PageDown และ PageUp รวมถึงเมื่อคำนวณจำนวนการเลื่อนสำหรับElement.scrollIntoView()
การโต้ตอบกับ API การเลื่อนอื่นๆ
DOM Scrolling API
การเลื่อนแบบสแนปจะเกิดขึ้นหลังจากการดำเนินการเลื่อนทั้งหมด รวมถึงการดำเนินการที่สคริปต์เริ่มต้น เมื่อคุณใช้ API เช่น Element.scrollTo
เบราว์เซอร์จะคำนวณตำแหน่งการเลื่อนที่ต้องการของการดำเนินการ จากนั้นใช้ตรรกะการสแนปที่เหมาะสมเพื่อค้นหาตำแหน่งที่สแนปสุดท้าย ดังนั้นจึง
ไม่จำเป็นต้องใช้สคริปต์ผู้ใช้เพื่อทำการคำนวณด้วยตนเองสำหรับการสแนป
การเลื่อนอย่างราบรื่น
การเลื่อนที่ราบรื่นจะควบคุมลักษณะการทำงานของการดำเนินการเลื่อนแบบเป็นโปรแกรม ขณะที่ การเลื่อนแบบสแนปจะกำหนดปลายทาง เนื่องจากควบคุมลักษณะที่ตั้งฉากของการเลื่อน จึงใช้ร่วมกันและเสริมซึ่งกันและกันได้
ลักษณะการทำงานของการเลื่อนเกิน
API ลักษณะการทำงานของการเลื่อนเกินจะควบคุมวิธี การเลื่อนที่เชื่อมโยงในองค์ประกอบหลายรายการ และจะไม่ได้รับผลกระทบจากการเลื่อน สแนป
ข้อควรระวังและแนวทางปฏิบัติแนะนำ
หลีกเลี่ยงการใช้การสแนปที่บังคับเมื่อองค์ประกอบเป้าหมายอยู่ห่างกันมาก ซึ่งอาจทำให้เข้าถึงเนื้อหาที่อยู่ระหว่างตำแหน่งสแนปไม่ได้
ในหลายกรณี คุณสามารถเพิ่มการเลื่อนแบบสแนปเป็นการเพิ่มประสิทธิภาพ
โดยไม่ต้องตรวจหาฟีเจอร์
หากจำเป็น ให้ใช้ @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
จะเลื่อนไปถึงออฟเซ็ตการเลื่อนที่ขอเสมอ การเลื่อนแบบสแนปอาจปรับ
ออฟเซ็ตการเลื่อนหลังจากที่การเลื่อนแบบเป็นโปรแกรมเสร็จสมบูรณ์ โปรดทราบว่านี่ไม่ใช่สมมติฐานที่ดีแม้ก่อนที่จะมีการเลื่อนสแนป เนื่องจากอาจมีการขัดจังหวะการเลื่อนด้วยเหตุผลอื่นๆ แต่กรณีนี้จะเกิดขึ้นโดยเฉพาะกับการเลื่อนสแนป
งานในอนาคต
ประสบการณ์การเลื่อนเป็นหัวใจสำคัญของแบบสำรวจล่าสุดของทีม Chrome
ผลสำรวจระบุหลายด้านที่ต้องดำเนินการเพิ่มเติม
เพื่อลดช่องว่างระหว่างไลบรารีปลั๊กอินกับ CSS
งานที่กำลังจะดำเนินการจะมุ่งเน้นไปที่ scroll-snap
ซึ่งรวมถึง
- ความพร้อมใช้งานและความเข้ากันได้ของ API ในเบราว์เซอร์ต่างๆ
- ทำงานกับ API ใหม่ของ CSS เช่น
scroll-start
- ทำงานกับเหตุการณ์ JS ใหม่ เช่น
snapChanged()