ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างประสบการณ์การใช้งานที่คล้ายกับ Instagram Stories บนเว็บ
ในโพสต์นี้ ฉันต้องการแชร์แนวคิดเกี่ยวกับการสร้างคอมโพเนนต์ Stories สำหรับเว็บที่ปรับเปลี่ยนตามอุปกรณ์ รองรับการไปยังส่วนต่างๆ ด้วยแป้นพิมพ์ และทำงานในเบราว์เซอร์ต่างๆ ได้
หากต้องการดูการสาธิตการสร้างคอมโพเนนต์ Stories ด้วยตนเอง โปรดดู Codelab สำหรับคอมโพเนนต์ Stories
หากคุณชอบดูวิดีโอมากกว่า เรามีโพสต์นี้ในเวอร์ชัน YouTube ด้วย
ภาพรวม
ตัวอย่าง UX ของ Stories ที่ได้รับความนิยม 2 รายการ ได้แก่ Snapchat Stories และ Instagram Stories (ยังไม่รวม Fleets) ในแง่ของ UX ทั่วไป เรื่องราวมักจะเป็นรูปแบบที่เน้นการแตะบนอุปกรณ์เคลื่อนที่เท่านั้นสำหรับการไปยังส่วนต่างๆ ของการสมัครใช้บริการหลายรายการ ตัวอย่างเช่น ใน Instagram ผู้ใช้จะเปิดสตอรี่ของเพื่อนและดูรูปภาพในสตอรี่นั้น โดยทั่วไปแล้ว ผู้เล่นจะส่งคำขอเป็นเพื่อนให้ผู้เล่นหลายคนพร้อมกัน เมื่อแตะที่ด้านขวาของอุปกรณ์ ผู้ใช้จะข้ามไปยังเรื่องราวถัดไปของเพื่อนคนนั้น การปัดไปทางขวาจะทำให้ผู้ใช้ข้ามไปยังเพื่อนคนอื่น คอมโพเนนต์เรื่องราวค่อนข้างคล้ายกับภาพสไลด์ แต่ช่วยให้ไปยังส่วนต่างๆ ของอาร์เรย์หลายมิติได้ ซึ่งต่างจากอาร์เรย์มิติเดียว เหมือนกับว่ามีภาพสไลด์อยู่ภายในภาพสไลด์แต่ละรายการ 🤯
ภาพสไลด์ "ซ้อน" ที่ 2 ของเรื่องราว
👍 รายการในรายการ หรือที่เรียกว่าอาร์เรย์หลายมิติ
การเลือกเครื่องมือที่เหมาะสมสำหรับงาน
โดยรวมแล้ว ฉันพบว่าคอมโพเนนต์นี้สร้างได้ค่อนข้างตรงไปตรงมา เนื่องจากมีฟีเจอร์แพลตฟอร์มเว็บที่สำคัญบางอย่าง มาดูรายละเอียดกันเลย
ตารางกริด CSS
เลย์เอาต์ของเราไม่ได้เป็นเรื่องยากสำหรับ CSS Grid เนื่องจากมีวิธีที่มีประสิทธิภาพในการจัดการเนื้อหา
เลย์เอาต์ Friends
คอมโพเนนต์ Wrapper หลักของ .stories คือมุมมองการเลื่อนแนวนอนที่เน้นอุปกรณ์เคลื่อนที่เป็นหลัก
.stories {
inline-size: 100vw;
block-size: 100vh;
display: grid;
grid: 1fr / auto-flow 100%;
gap: 1ch;
overflow-x: auto;
scroll-snap-type: x mandatory;
overscroll-behavior: contain;
touch-action: pan-x;
}
/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
max-inline-size: 480px;
max-block-size: 848px;
}
มาดูรายละเอียดของเลย์เอาต์ grid กัน
- เราเติมวิวพอร์ตบนอุปกรณ์เคลื่อนที่ด้วย
100vhและ100vwอย่างชัดเจน และจำกัดขนาดบนเดสก์ท็อป /แยกเทมเพลตแถวและคอลัมน์ของเราauto-flowแปลเป็นgrid-auto-flow: column- เทมเพลตการจัดเรียงอัตโนมัติคือ
100%ซึ่งในกรณีนี้คือความกว้างของหน้าต่างการเลื่อน
ในโทรศัพท์มือถือ ให้คิดว่าขนาดแถวคือความสูงของวิวพอร์ต และแต่ละคอลัมน์คือความกว้างของวิวพอร์ต ต่อจากตัวอย่าง Snapchat Stories และ Instagram Stories แต่ละคอลัมน์จะเป็นเรื่องราวของเพื่อน เราต้องการให้เรื่องราวของเพื่อนๆ ดำเนินต่อไปนอกวิวพอร์ตเพื่อให้เรามีที่ให้เลื่อนดู Grid จะสร้างคอลัมน์จำนวนเท่าใดก็ได้ที่จำเป็นต่อการจัดวาง HTML สำหรับเรื่องราวของเพื่อนแต่ละคน โดยสร้างคอนเทนเนอร์การเลื่อนแบบไดนามิกและปรับเปลี่ยนตามอุปกรณ์ให้เรา ตารางกริดช่วยให้เราสามารถรวมเอฟเฟกต์ทั้งหมดไว้ที่ศูนย์กลางได้
การซ้อนกัน
สำหรับเพื่อนแต่ละคน เราต้องการเรื่องราวของพวกเขาในสถานะที่พร้อมสำหรับการแบ่งหน้า ฉันเลือกใช้ Stack เพื่อเตรียมพร้อมสำหรับภาพเคลื่อนไหวและรูปแบบสนุกๆ อื่นๆ เมื่อพูดถึงการซ้อนกัน หมายความว่าคุณกำลังมองลงไปที่แซนด์วิช ไม่ใช่การมองจากด้านข้าง
เมื่อใช้ CSS Grid เราสามารถกำหนดตารางกริดแบบเซลล์เดียว (เช่น สี่เหลี่ยมจัตุรัส) โดยที่แถวและคอลัมน์ใช้นามแฝงร่วมกัน ([story]) จากนั้นระบบจะกำหนดองค์ประกอบย่อยแต่ละรายการให้กับพื้นที่เซลล์เดียวที่มีนามแฝงนั้น
.user {
display: grid;
grid: [story] 1fr / [story] 1fr;
scroll-snap-align: start;
scroll-snap-stop: always;
}
.story {
grid-area: story;
background-size: cover;
…
}
ซึ่งจะทำให้ HTML ของเราควบคุมลำดับการซ้อนและยังคงองค์ประกอบทั้งหมดไว้ในโฟลว์ สังเกตว่าเราไม่จำเป็นต้องทำอะไรกับการจัดตำแหน่ง absolute หรือ z-index และเราไม่จำเป็นต้องแก้ไขกล่องด้วย height: 100% หรือ width: 100% ตารางกริดหลักได้กำหนดขนาดของวิวพอร์ตภาพเรื่องราวไว้แล้ว ดังนั้นจึงไม่จำเป็นต้องบอกให้คอมโพเนนต์เรื่องราวเหล่านี้เติมเต็มวิวพอร์ต
จุดสแนปการเลื่อน CSS
ข้อกำหนด CSS Scroll Snap Points ช่วยให้ล็อกองค์ประกอบในวิวพอร์ตเมื่อเลื่อนได้ง่ายๆ ก่อนที่จะมีพร็อพเพอร์ตี้ CSS เหล่านี้ คุณต้องใช้ JavaScript ซึ่งค่อนข้าง… ยุ่งยากเลยทีเดียว ดูการแนะนำจุดสแนปการเลื่อน CSS โดย Sarah Drasner เพื่อดูรายละเอียดที่ยอดเยี่ยมเกี่ยวกับวิธีใช้
scroll-snap-points
หากไม่มี ผู้ใช้จะเลื่อนดูได้อย่างอิสระตามปกติ ซึ่งจะช่วยให้เบราว์เซอร์วางอยู่บนแต่ละรายการอย่างนุ่มนวล
.stories { display: grid; grid: 1fr / auto-flow 100%; gap: 1ch; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior: contain; touch-action: pan-x; }
.user { display: grid; grid: [story] 1fr / [story] 1fr; scroll-snap-align: start; scroll-snap-stop: always; }
ฉันเลือก Scroll Snap Points ด้วยเหตุผล 2-3 ประการดังนี้
- การช่วยเหลือพิเศษฟรี ข้อกำหนดของ Scroll Snap Points ระบุว่าการกดปุ่มลูกศรซ้ายและลูกศรขวาควรเลื่อนผ่านจุดสแนปโดยค่าเริ่มต้น
- ข้อกำหนดที่เพิ่มขึ้น ข้อกำหนดจุดสแนปการเลื่อนมีฟีเจอร์ใหม่และการปรับปรุงอยู่ตลอดเวลา ซึ่งหมายความว่าคอมโพเนนต์ Stories ของฉันน่าจะดีขึ้นเรื่อยๆ นับจากนี้ไป
- ความง่ายในการติดตั้งใช้งาน จุดสแนปการเลื่อนสร้างขึ้นมาเพื่อกรณีการใช้งานการแบ่งหน้าแนวนอนที่เน้นการสัมผัสโดยเฉพาะ
- เกมแพลตฟอร์มสไตล์ Inertia ฟรี ทุกแพลตฟอร์มจะเลื่อนและหยุดในรูปแบบของตัวเอง ซึ่งต่างจากแรงเฉื่อยที่ปรับให้สอดคล้องกันซึ่งอาจมีรูปแบบการเลื่อนและหยุดที่แปลกตา
ความเข้ากันได้ในเบราว์เซอร์ต่างๆ
เราได้ทดสอบใน Opera, Firefox, Safari และ Chrome รวมถึง Android และ iOS ต่อไปนี้เป็นข้อมูลสรุปสั้นๆ เกี่ยวกับฟีเจอร์บนเว็บที่เราพบความแตกต่างในด้านความสามารถและการรองรับ
อย่างไรก็ตาม เรามี CSS บางส่วนที่ไม่ได้ใช้ ดังนั้นบางแพลตฟอร์มจึงไม่ได้รับประโยชน์จากการเพิ่มประสิทธิภาพ UX ในขณะนี้ ฉันชอบที่ไม่ต้องจัดการฟีเจอร์เหล่านี้และมั่นใจว่าในที่สุดฟีเจอร์เหล่านี้จะเข้าถึงเบราว์เซอร์และแพลตฟอร์มอื่นๆ ได้
scroll-snap-stop
ภาพสไลด์เป็นหนึ่งใน Use Case หลักของ UX ที่กระตุ้นให้เกิดการสร้างข้อกำหนดเฉพาะของจุดสแนปการเลื่อน CSS ภาพสไลด์ไม่จำเป็นต้องหยุดที่รูปภาพแต่ละรูปเสมอไปหลังจากที่ผู้ใช้โต้ตอบกับรูปภาพนั้น ซึ่งต่างจากเรื่องราว การเลื่อนดูภาพสไลด์อย่างรวดเร็วอาจเป็นเรื่องปกติหรือเป็นสิ่งที่ควรทำ ในทางกลับกัน เรื่องราวจะเหมาะกับการดูทีละเรื่องมากกว่า ซึ่ง scroll-snap-stop ก็มีฟีเจอร์นี้ให้ใช้งาน
.user {
scroll-snap-align: start;
scroll-snap-stop: always;
}
ในขณะที่เขียนโพสต์นี้ scroll-snap-stop รองรับเฉพาะในเบราว์เซอร์ที่ใช้ Chromium เท่านั้น ดูข้อมูลอัปเดตเกี่ยวกับความเข้ากันได้กับเบราว์เซอร์ แต่ก็ไม่ใช่ปัญหาที่บล็อกการทำงาน แต่หมายความว่าในเบราว์เซอร์ที่ไม่รองรับ
ผู้ใช้อาจข้ามเพื่อนโดยไม่ตั้งใจได้ ดังนั้นผู้ใช้จะต้องระมัดระวังมากขึ้น หรือเราจะต้องเขียน JavaScript เพื่อให้แน่ใจว่าเพื่อนที่ถูกข้ามจะไม่ถูกทำเครื่องหมายว่าดูแล้ว
อ่านข้อมูลเพิ่มเติมได้ในข้อกำหนดหากสนใจ
overscroll-behavior
คุณเคยเลื่อนดูโมดัลแล้วจู่ๆ ก็เริ่มเลื่อนดูเนื้อหาที่อยู่ด้านหลังโมดัลไหม
overscroll-behavior
ช่วยให้นักพัฒนาแอปดักจับการเลื่อนนั้นและไม่ปล่อยให้เลื่อนออกไปได้ เหมาะสำหรับทุกโอกาส คอมโพเนนต์ My Stories ใช้ฟีเจอร์นี้เพื่อป้องกันไม่ให้การปัดและการเลื่อนเพิ่มเติมออกจากคอมโพเนนต์
.stories {
overflow-x: auto;
overscroll-behavior: contain;
}
Safari และ Opera เป็น 2 เบราว์เซอร์ที่ไม่รองรับฟีเจอร์นี้ ซึ่งก็ไม่เป็นไร ผู้ใช้เหล่านั้นจะได้รับประสบการณ์การเลื่อนเกินขอบเขตเหมือนที่เคยใช้ และอาจไม่สังเกตเห็นการปรับปรุงนี้เลย โดยส่วนตัวแล้วฉันชอบฟีเจอร์นี้มากและชอบรวมไว้เป็นส่วนหนึ่งของฟีเจอร์การเลื่อนเกินที่ฉันใช้เกือบทุกฟีเจอร์ การเพิ่มนี้ไม่เป็นอันตรายและมีแต่จะช่วยปรับปรุง UX
scrollIntoView({behavior: 'smooth'})
เมื่อผู้ใช้แตะหรือคลิกและดูชุดเรื่องราวของเพื่อนจนจบแล้ว ก็ถึงเวลาที่จะย้ายไปยังเพื่อนคนถัดไปในชุดจุดสแนปการเลื่อน เมื่อใช้ JavaScript เราจะอ้างอิงเพื่อนคนถัดไปและขอให้เลื่อนเพื่อนคนนั้นเข้ามาในมุมมองได้ การรองรับพื้นฐานของฟีเจอร์นี้ยอดเยี่ยมมาก ทุกเบราว์เซอร์เลื่อนองค์ประกอบเข้ามาในมุมมอง แต่ไม่ใช่ทุกเบราว์เซอร์ที่ทำเช่นนั้น 'smooth' ซึ่งหมายความว่า
ระบบจะเลื่อนโฆษณาเข้ามาในมุมมองแทนที่จะแสดงทันที
element.scrollIntoView({
behavior: 'smooth'
})
Safari เป็นเบราว์เซอร์เดียวที่ไม่รองรับbehavior: 'smooth'ที่นี่ ดูข้อมูลอัปเดตเกี่ยวกับความเข้ากันได้กับเบราว์เซอร์
ลงมือทำ
ตอนนี้คุณก็รู้แล้วว่าเราทำยังไง แล้วคุณล่ะจะทำยังไง มาปรับเปลี่ยนแนวทางและเรียนรู้วิธีทั้งหมดในการสร้างสรรค์บนเว็บกัน สร้างเดโม ทวีตเวอร์ชันของคุณมาให้ฉัน แล้วฉันจะเพิ่มลงในส่วนรีมิกซ์ของชุมชนด้านล่าง
รีมิกซ์ของชุมชน
- @geoffrich_ กับ Svelte: โค้ด
- @GauteMeekOlsen ที่ใช้ Vue: เดโม + โค้ด
- @AnaestheticsApp ที่ใช้ Lit: โค้ด