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

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

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

สาธิต

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

หากต้องการดูวิดีโอ โปรดดูโพสต์เวอร์ชัน YouTube ที่นี่

ภาพรวม

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

อาร์เรย์หลายมิติที่แสดงเป็นภาพโดยใช้การ์ด จากซ้ายไปขวาคือกองการ์ดที่มีขอบสีม่วง และภายในการ์ดแต่ละใบมีการ์ดที่มีขอบสีฟ้าซีน 1-หลายใบ รายการในรายการ
ภาพสไลด์ของเพื่อนชุดที่ 1
ภาพสไลด์ "ซ้อนกัน" ชุดที่ 2 ของเรื่องราว
👍 รายการในรายการ หรือที่เรียกว่าอาร์เรย์หลายมิติ

การเลือกเครื่องมือที่เหมาะสมกับงาน

โดยรวมแล้ว เราพบว่าการสร้างคอมโพเนนต์นี้ค่อนข้างตรงไปตรงมา เนื่องด้วยฟีเจอร์สําคัญบางอย่างของแพลตฟอร์มเว็บ มาเริ่มกันเลย

CSS Grid

เลยพบว่าเลย์เอาต์ของเรานั้นไม่ยากสำหรับ CSS Grid เนื่องจากมีวิธีจัดการเนื้อหาที่มีประสิทธิภาพ

เลย์เอาต์เพื่อน

Wrapper คอมโพเนนต์ .stories หลักของเราคือ ScrollView แนวนอนเพื่ออุปกรณ์เคลื่อนที่เป็นอันดับแรก

.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 กัน

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

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

การซ้อน

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

ตารางกริด 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 ช่วยให้คุณล็อกองค์ประกอบไว้ในวิวพอร์ตเมื่อเลื่อนได้อย่างง่ายดาย ก่อนหน้านี้ คุณต้องใช้ 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;
}
เด็กเลือกที่จะเป็นผู้รับสแนป

เราเลือกจุดยึดการเลื่อนเนื่องจากเหตุผลต่อไปนี้

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

ความเข้ากันได้ในเบราว์เซอร์ต่างๆ

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

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

scroll-snap-stop

ภาพสไลด์เป็นหนึ่งใน Use Case หลักของ UX ที่กระตุ้นให้สร้างข้อกำหนดเกี่ยวกับจุดหยุดของ CSS Scroll ซึ่งแตกต่างจากเรื่องราวตรงที่ภาพสไลด์ไม่จำเป็นต้องหยุดที่รูปภาพแต่ละรูปเสมอไปหลังจากที่ผู้ใช้โต้ตอบกับรูปภาพ คุณอาจเลื่อนดูภาพสไลด์อย่างรวดเร็วได้ ในทางกลับกัน เรื่องราวควรดูทีละเรื่อง และ 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' ที่นี่ ดูข้อมูลอัปเดตเกี่ยวกับความเข้ากันได้กับเบราว์เซอร์

ลงมือปฏิบัติ

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

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