การสร้างคอมโพเนนต์เรื่องราว

ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างประสบการณ์การใช้งานที่คล้ายกับ Instagram Stories บนเว็บ

ในโพสต์นี้ ฉันต้องการแชร์แนวคิดเกี่ยวกับการสร้างคอมโพเนนต์ Stories สำหรับเว็บที่ปรับเปลี่ยนตามอุปกรณ์ รองรับการไปยังส่วนต่างๆ ด้วยแป้นพิมพ์ และทำงานในเบราว์เซอร์ต่างๆ ได้

สาธิต

หากต้องการดูการสาธิตการสร้างคอมโพเนนต์ Stories ด้วยตนเอง โปรดดู Codelab สำหรับคอมโพเนนต์ Stories

หากคุณชอบดูวิดีโอมากกว่า เรามีโพสต์นี้ในเวอร์ชัน YouTube ด้วย

ภาพรวม

ตัวอย่าง UX ของ Stories ที่ได้รับความนิยม 2 รายการ ได้แก่ Snapchat Stories และ Instagram Stories (ยังไม่รวม Fleets) ในแง่ของ UX ทั่วไป เรื่องราวมักจะเป็นรูปแบบที่เน้นการแตะบนอุปกรณ์เคลื่อนที่เท่านั้นสำหรับการไปยังส่วนต่างๆ ของการสมัครใช้บริการหลายรายการ ตัวอย่างเช่น ใน Instagram ผู้ใช้จะเปิดสตอรี่ของเพื่อนและดูรูปภาพในสตอรี่นั้น โดยทั่วไปแล้ว ผู้เล่นจะส่งคำขอเป็นเพื่อนให้ผู้เล่นหลายคนพร้อมกัน เมื่อแตะที่ด้านขวาของอุปกรณ์ ผู้ใช้จะข้ามไปยังเรื่องราวถัดไปของเพื่อนคนนั้น การปัดไปทางขวาจะทำให้ผู้ใช้ข้ามไปยังเพื่อนคนอื่น คอมโพเนนต์เรื่องราวค่อนข้างคล้ายกับภาพสไลด์ แต่ช่วยให้ไปยังส่วนต่างๆ ของอาร์เรย์หลายมิติได้ ซึ่งต่างจากอาร์เรย์มิติเดียว เหมือนกับว่ามีภาพสไลด์อยู่ภายในภาพสไลด์แต่ละรายการ 🤯

อาร์เรย์หลายมิติที่แสดงภาพโดยใช้การ์ด จากซ้ายไปขวาคือการ์ดขอบสีม่วงที่ซ้อนกัน และภายในการ์ดแต่ละใบคือการ์ดขอบสีฟ้า 1 ใบหรือมากกว่านั้น รายการในรายการ
ภาพสไลด์แรกของเพื่อน
ภาพสไลด์ "ซ้อน" ที่ 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;
}
การใช้โหมดอุปกรณ์ของเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome เพื่อไฮไลต์คอลัมน์ที่สร้างโดย Grid

มาดูรายละเอียดของเลย์เอาต์ 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'ที่นี่ ดูข้อมูลอัปเดตเกี่ยวกับความเข้ากันได้กับเบราว์เซอร์

ลงมือทำ

ตอนนี้คุณก็รู้แล้วว่าเราทำยังไง แล้วคุณล่ะจะทำยังไง มาปรับเปลี่ยนแนวทางและเรียนรู้วิธีทั้งหมดในการสร้างสรรค์บนเว็บกัน สร้างเดโม ทวีตเวอร์ชันของคุณมาให้ฉัน แล้วฉันจะเพิ่มลงในส่วนรีมิกซ์ของชุมชนด้านล่าง

รีมิกซ์ของชุมชน