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

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

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

การสาธิต

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

หากชอบวิดีโอ นี่คือโพสต์นี้เวอร์ชัน YouTube

ภาพรวม

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

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

มาดูรายละเอียดเกี่ยวกับเลย์เอาต์ของ grid กัน

  • เราแก้ไขวิวพอร์ตบนอุปกรณ์เคลื่อนที่อย่างชัดแจ้งด้วย 100vh และ 100vw และจำกัดขนาดบนเดสก์ท็อป
  • / แยกเทมเพลตแถวและคอลัมน์ออกจากกัน
  • auto-flow แปลว่า grid-auto-flow: column
  • เทมเพลตโฟลว์อัตโนมัติคือ 100% ซึ่งในกรณีนี้คือตามความกว้างของหน้าต่างที่เลื่อน

ในโทรศัพท์มือถือ ให้คิดว่าขนาดแถวคือความสูงของวิวพอร์ต และแต่ละคอลัมน์คือความกว้างของวิวพอร์ต จากตัวอย่าง Snapchat Stories และ เรื่องราว Instagram แต่ละคอลัมน์จะเป็นเรื่องราวของเพื่อน เราอยากให้มีเรื่องราวกับเพื่อนๆ ต่อไปเรื่อยๆ นอกวิวพอร์ต เพื่อให้เรามีที่ที่ต้องเลื่อนดู ตารางกริดจะสร้างคอลัมน์ที่ต้องใช้ในการจัดวาง HTML สำหรับเรื่องราวของเพื่อนแต่ละเรื่องเพื่อสร้างคอนเทนเนอร์แบบเลื่อนที่ปรับเปลี่ยนตามอุปกรณ์ให้เรา ตารางกริดช่วยให้เรารวม เอฟเฟกต์ทั้งหมดไว้ในที่เดียว

กองซ้อน

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

เมื่อใช้ตารางกริด CSS เราจะกำหนดตารางกริดแบบเซลล์เดียว (สี่เหลี่ยมจัตุรัส) ซึ่งแถวและคอลัมน์จะใช้ชื่อแทน ([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 ช่วยให้ล็อกองค์ประกอบต่างๆ ในวิวพอร์ตขณะเลื่อนได้อย่างง่ายดาย ก่อนที่จะมีพร็อพเพอร์ตี้ CSS เหล่านี้ คุณต้องใช้ JavaScript ซึ่งก็ค่อนข้างยาก ลองอ่าน ขอแนะนำ CSS Scroll Snap Points ของ Sarah Drasner เพื่อดูรายละเอียดเกี่ยวกับวิธีใช้

การเลื่อนแนวนอนโดยไม่มีรูปแบบ scroll-snap-points หากไม่มี ผู้ใช้ก็จะเลื่อนได้ตามปกติ ด้วยการทำเช่นนี้ เบราว์เซอร์จะค่อยๆ วางใจในแต่ละรายการ
parent
.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 ประการคือ

  • การช่วยเหลือพิเศษฟรี ข้อมูลจำเพาะของการเลื่อน Snap Point ระบุว่าการกดแป้นลูกศรซ้ายและลูกศรขวาควรเลื่อนผ่านจุดสแนปโดยค่าเริ่มต้น
  • ข้อมูลจำเพาะที่เพิ่มขึ้น ข้อมูลจำเพาะของ Scroll Snap Points ได้รับฟีเจอร์และการปรับปรุงใหม่ๆ ตลอดเวลา ซึ่งหมายความว่าคอมโพเนนต์เรื่องราวของฉันน่าจะดีขึ้นกว่าเดิมเท่านั้น
  • ใช้งานง่าย จุด Snap ของการเลื่อนสร้างขึ้นเพื่อการใช้งานสำหรับกรณีการใช้งานที่มีการแบ่งหน้าในแนวนอนที่เน้นการแตะ
  • ความเฉื่อยแบบแพลตฟอร์มฟรี ทุกแพลตฟอร์มจะเลื่อนและวางตัวตามสไตล์ของตน ซึ่งตรงข้ามกับความเฉื่อยมาตรฐานซึ่งอาจมีรูปแบบการเลื่อนและการเคลื่อนไหวที่แปลกประหลาด

ความสามารถในการใช้งานร่วมกันข้ามเบราว์เซอร์

เราทดสอบใน Opera, Firefox, Safari และ Chrome รวมถึง Android และ iOS ต่อไปนี้เป็นคำอธิบายโดยย่อของฟีเจอร์บนเว็บที่เราพบความแตกต่างด้านความสามารถและการสนับสนุน

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

scroll-snap-stop

ภาพสไลด์เป็นหนึ่งใน Use Case หลัก UX ที่ส่งผลให้เกิดการสร้างข้อกำหนดเฉพาะของ CSS Scroll Snap Points ซึ่งต่างจากเรื่องราวตรงที่ภาพสไลด์ไม่จำเป็นต้องหยุดกับแต่ละรูปภาพหลังจากที่ผู้ใช้โต้ตอบกับรูปแล้วเสมอไป ขอแนะนำให้หมุนภาพสไลด์อย่างรวดเร็ว ในทางตรงกันข้าม เรื่องราวจะเลือกไปทีละเรื่องได้ดีที่สุด และ scroll-snap-stop ก็แนะนำเนื้อหาได้ดี

.user {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

ในขณะที่เขียนโพสต์นี้ scroll-snap-stop ได้รับการสนับสนุนเฉพาะในเบราว์เซอร์แบบ Chromium เท่านั้น โปรดดูความเข้ากันได้ของเบราว์เซอร์สำหรับการอัปเดต แต่สิ่งนี้ไม่ใช่ตัวบล็อก แต่หมายความว่าบนเบราว์เซอร์ที่ไม่รองรับ ผู้ใช้อาจข้ามเพื่อนโดยไม่ตั้งใจได้ ดังนั้นผู้ใช้จึงต้องใช้ความระมัดระวังมากขึ้น หรือเราจะต้องเขียน JavaScript เพื่อไม่ให้เพื่อนที่ถูกข้ามว่าดูแล้ว

อ่านเพิ่มเติมในข้อกำหนดหากคุณสนใจ

overscroll-behavior

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

.stories {
  overflow-x: auto;
  overscroll-behavior: contain;
}

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

scrollIntoView({behavior: 'smooth'})

เมื่อผู้ใช้แตะหรือคลิกจบชุดเรื่องราวของเพื่อนแล้ว ถึงเวลาย้ายไปที่เพื่อนคนถัดไปในชุดจุดเลื่อนของการเลื่อน ด้วย JavaScript ทำให้เราสามารถอ้างอิงเพื่อนคนถัดไปและขอให้เลื่อนเข้ามาในมุมมองได้ การสนับสนุนข้อมูลพื้นฐานเกี่ยวกับเรื่องนี้เป็นอย่างดี เบราว์เซอร์ทุกชนิด เลื่อนดูจนครบ แต่ไม่ใช่ทุกเบราว์เซอร์ 'smooth' เพียงแต่หมายความว่า มีการเลื่อนมุมมองเข้ามาในมุมมองแทนที่จะสแนป

element.scrollIntoView({
  behavior: 'smooth'
})

Safari เป็นเบราว์เซอร์เดียวที่ไม่รองรับ behavior: 'smooth' ที่นี่ โปรดดูความเข้ากันได้ของเบราว์เซอร์สำหรับการอัปเดต

ลงมือจริง

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

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