สร้างประสบการณ์การเลื่อนที่มีการควบคุมเป็นอย่างดีโดยการประกาศตำแหน่งการสแนปการเลื่อน
ฟีเจอร์การสแนปการเลื่อน CSS ช่วยให้นักพัฒนาเว็บสร้างประสบการณ์การเลื่อนที่มีการควบคุมเป็นอย่างดีด้วยการประกาศตำแหน่งการสแนปการเลื่อน บทความที่ใส่เลขหน้าและภาพหมุนเป็นตัวอย่างที่มีการใช้โดยทั่วไป CSS Scroll Snap มี API แบบใช้ง่ายและสอดคล้องกันสำหรับสร้างรูปแบบ UX ยอดนิยมเหล่านี้
ข้อมูลเบื้องต้น
เคสสำหรับการเลื่อนการสแนป
การเลื่อนเป็นวิธีที่ได้รับความนิยมและเป็นธรรมชาติในการโต้ตอบกับเนื้อหาบนเว็บ ซึ่งเป็นวิธีการแบบเดิมของแพลตฟอร์มในการให้สิทธิ์เข้าถึงข้อมูลมากกว่าการปรากฏบนหน้าจอพร้อมกัน ซึ่งมีความสำคัญเป็นพิเศษในแพลตฟอร์มอุปกรณ์เคลื่อนที่ที่มีพื้นที่หน้าจอที่จำกัด จึงไม่น่าแปลกใจที่ผู้เขียนเว็บจะชอบจัดระเบียบเนื้อหาไปยังรายการแบบแบนราบที่เลื่อนได้ แทนที่จะเป็นลำดับชั้นที่ลึกมาก
ข้อเสียหลักของการเลื่อนคือความแม่นยำ ไม่บ่อยนักที่การเลื่อนเลื่อนไปแนวเดียวกับย่อหน้าหรือประโยค วิธีนี้จะเห็นได้ชัดเจนยิ่งขึ้นสำหรับเนื้อหาที่มีการแบ่งหน้าหรือแบ่งย่อยเนื้อหาซึ่งมีขอบเขตที่มีความหมายเมื่อเลื่อนจนสุดหน้าหรือภาพตรงกลางหน้าหรือรูปภาพ ทำให้มองเห็นได้บางส่วน กรณีการใช้งานเหล่านี้จะได้ประโยชน์จากประสบการณ์การเลื่อนที่ควบคุมได้ดี
นักพัฒนาเว็บพึ่งพาโซลูชันแบบ 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
หมายความว่าขอบเริ่มต้นของสแนปพอร์ตของคอนเทนเนอร์แบบเลื่อนควรล้างออกด้วยขอบเริ่มต้นพื้นที่สแนปองค์ประกอบ ในทำนองเดียวกัน การจัดแนว 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 ใหม่ที่สามารถใช้ปรับขอบเขตที่มองเห็นได้ของคอนเทนเนอร์แบบเลื่อนหรือสแนปพอร์ต ซึ่งใช้ในการคำนวณการปรับแนวการเลื่อนสแนปได้ พร็อพเพอร์ตี้กำหนดส่วนที่เสริมจากช่องระยะห่างจากขอบของคอนเทนเนอร์ที่เลื่อน ในตัวอย่างของเรา เราได้เพิ่ม15vh
การฝังเพิ่มเติมไว้ที่ด้านบน ซึ่งจะบอกให้เบราว์เซอร์พิจารณาตำแหน่งที่ต่ำกว่า 15vh
ใต้ขอบด้านบนของคอนเทนเนอร์การเลื่อน เพื่อเป็นขอบเริ่มต้นแนวตั้งสำหรับการเลื่อน เมื่อสแนป ขอบเริ่มต้นขององค์ประกอบเป้าหมายสแนปจะล้างออกด้วยตำแหน่งใหม่นี้ จึงเว้นช่องว่างด้านบนไว้
พร็อพเพอร์ตี้ scroll-margin
กำหนดจำนวนการเริ่มต้นที่ใช้เพื่อปรับกล่องที่มีประสิทธิภาพของเป้าหมายการยึด ซึ่งคล้ายกับวิธีที่ scroll-padding
ทำงานในคอนเทนเนอร์การเลื่อนการยึด
คุณอาจสังเกตเห็นว่าพร็อพเพอร์ตี้ทั้ง 2 รายการไม่มีคำว่า "snap
" เป็นไปอย่างที่ตั้งใจ เนื่องจากบริษัทจะแก้ไขช่องสำหรับการดำเนินการเลื่อนที่เกี่ยวข้องทั้งหมด ไม่ใช่แค่การสแนปการเลื่อน ตัวอย่างเช่น Chrome จะคำนวณขนาดหน้าสำหรับการเลื่อนการแบ่งหน้า เช่น PageDown และ PageUp และขณะคำนวณปริมาณการเลื่อนสำหรับการดำเนินการ Element.scrollIntoView()
ด้วย
การโต้ตอบกับ API แบบเลื่อนอื่นๆ
API เลื่อน DOM
การสแนปการเลื่อนจะเกิดขึ้นหลังการดำเนินการเลื่อนทั้งหมด รวมถึงการดำเนินการที่เริ่มต้นโดยสคริปต์ เมื่อคุณใช้ API เช่น Element.scrollTo
เบราว์เซอร์จะคำนวณตำแหน่งการเลื่อนที่ต้องการของการดำเนินการ จากนั้นจะใช้ตรรกะการยึดที่เหมาะสมเพื่อค้นหาตำแหน่งสุดท้ายที่ยึด ดังนั้น สคริปต์ของผู้ใช้จึงไม่จำเป็นต้องทำการคำนวณใดๆ สำหรับการจับคู่
การเลื่อนอย่างราบรื่น
การเลื่อนอย่างราบรื่นจะควบคุมลักษณะการทํางานของการเลื่อนแบบเป็นโปรแกรม ขณะที่การเลื่อนไปยังส่วนที่ต้องการจะกําหนดปลายทาง เนื่องจากเครื่องมือควบคุมการเลื่อนแง่มุมตั้งฉาก จึงสามารถใช้ร่วมกันและเสริมซึ่งกันและกันได้
ลักษณะการทำงานของการเลื่อนเกิน
Overscroll Behavior 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 ในเบราว์เซอร์ต่างๆ
- ทำงานเกี่ยวกับ CSS API ใหม่ เช่น
scroll-start
- ทำงานบน
เหตุการณ์ JS ใหม่ เช่น
snapChanged()