7 คะแนน โดย GN⁺ 2025-04-05 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Anchor Link มีโครงสร้างง่าย ๆ คือคลิกปุ่ม → เลื่อนไปยังหัวข้อ แต่เมื่อนำไปใช้งานจริงกลับเกิดปัญหาขึ้น
  • หัวข้อที่อยู่ด้านล่างจะไม่ถูกเลื่อนไปอยู่ชิดด้านบนของ viewport อย่างแม่นยำ ส่งผลให้ UX แย่ลง
  • เพื่อแก้ปัญหานี้ จึงมีการลองใช้หลายแนวทาง และค่อย ๆ พัฒนาไปสู่รูปแบบที่ละเอียดและซับซ้อนมากขึ้น

วิธีแก้แบบง่าย: เพิ่ม padding

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

วิธีแก้เชิงปฏิบัติ: ย้าย trigger line

  • ย้าย trigger line ลงไปทางด้านล่างของ viewport เพื่อให้หัวข้อด้านล่างไปถึงเส้นนั้นได้
  • ปัญหาคือหัวข้อจะไปอยู่ตรงล่างสุดของ viewport ทำให้ อ่านได้ยากขึ้น

แนวทางปรับปรุง: สร้าง virtual trigger point

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

วิธีที่ดีกว่า: เลื่อนตำแหน่ง trigger แบบแปรผันตามสัดส่วน

  • ไม่ได้เลื่อนทุก trigger เท่ากัน แต่ หัวข้อแรกคงเดิม ส่วนหัวข้อสุดท้ายเลื่อนได้มากที่สุด
  • หัวข้อระหว่างกลางจะ เลื่อนตามสัดส่วน ของตำแหน่ง
  • ตอบโจทย์ทั้ง การคงลำดับของหัวข้อ และ การรับประกันว่าสามารถเลื่อนไปถึงได้
  • วิธีนี้ เรียบง่ายและใช้ได้จริง และทำงานได้เหมาะสมในกรณีส่วนใหญ่

แนวทางขั้นสูง: ปรับให้เหมาะที่สุดด้วย custom mapping function

  • เนื่องจากตั้งตำแหน่ง trigger ไว้ที่ 25% แบบกำหนดเอง จึงทำให้ ตำแหน่งเสมือนอาจเบี่ยงจากตำแหน่งเดิมมากเกินไป
  • เพื่อแก้ปัญหานี้ จึงนำแนวทาง optimization ด้วย MSE(Mean Squared Error) มาใช้

การสร้าง loss function

  • Anchor Penalty: ระดับที่ตำแหน่งหัวข้อเสมือนเบี่ยงไปจากตำแหน่งเดิม
  • Section Penalty: ระดับการเปลี่ยนแปลงของระยะระหว่างแต่ละ section (ความยาวการเลื่อน)
  • ปรับน้ำหนักของทั้งสองค่านี้เพื่อหาตำแหน่ง trigger ที่เหมาะสมที่สุด

เงื่อนไขข้อจำกัด

  • ต้องอยู่ภายในขอบเขตของหน้า
  • หัวข้อแรกต้องไม่ถูกเลื่อนขึ้นด้านบน
  • ต้องรักษาลำดับของหัวข้อไว้

ข้อสังเกต: ข้อจำกัดของการเลื่อนแบบแปรผันตามสัดส่วนอย่างง่าย

  • ในหน้าที่ยาวมาก (เช่น พระคัมภีร์ทั้งเล่ม) จะเกิดความไม่มีประสิทธิภาพเพราะต้อง สะสมการเลื่อนเล็ก ๆ ตลอดทั้งหน้า
  • ยิ่งหน้ายาว ความคลาดเคลื่อนก็ยิ่งมาก และอาจส่งผลเสียต่อ UX

วิธีแก้สุดท้าย: ฟังก์ชัน mapping แบบแปรผันบนพื้นฐาน smoothstep

  • ทำ normalization ตำแหน่งของแต่ละหัวข้อให้อยู่ในช่วง 0~1 แล้วใช้ค่านั้นเป็นฐานในการ คำนวณอัตราการปรับ
  • ใช้ ฟังก์ชัน Smoothstep (S(x) = 3x² - 2x³) เพื่อสร้างการเปลี่ยนผ่านอย่างนุ่มนวล
  • กำหนดตำแหน่งเริ่มต้นการปรับ a เพื่อให้ก่อนถึงจุดหนึ่งจะยังไม่เลื่อน และหลังจากนั้นค่อย ๆ เพิ่มขึ้นอย่างนุ่มนวล
    • ตัวอย่าง: หาก a = 0.4 หัวข้อ 40% แรกจะไม่ถูกเลื่อน ส่วน 60% ล่างจะถูกปรับอย่างค่อยเป็นค่อยไป
  • ผลลัพธ์คือ หัวข้อด้านบนยังคงตำแหน่งเดิม ส่วนหัวข้อด้านล่างได้รับการปรับสูงสุด → มอบ UX ที่เป็นธรรมชาติ

การตรวจสอบและสรุป

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

1 ความคิดเห็น

 
GN⁺ 2025-04-05
ความคิดเห็นจาก Hacker News
  • ในฐานะนักพัฒนาแบ็กเอนด์ เวลาเห็นงานฝั่งฟรอนต์เอนด์บางครั้งก็รู้สึกทึ่งกับความซับซ้อน

    • เป็นบทความที่ยอดเยี่ยมและทำออกมาได้ดี แต่ก็อดสงสัยไม่ได้ว่าจำเป็นต้องใส่ความซับซ้อนมากขนาดนี้ให้กับการเลื่อนธรรมดาหรือไม่
  • ตั้งคำถามถึงเป้าหมายด้าน UX ของการแสดง "แองเคอร์ที่กำลังใช้งาน" ในเมนูนำทางด้านข้าง

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

    • ความสามารถในการบุ๊กมาร์กส่วนที่ต้องการได้โดยตรงสะดวกกว่าการเริ่มจากด้านบนของหน้าแล้วเลื่อนลงมา หรือคลิกลิงก์แองเคอร์มาก
    • เว็บไซต์นี้ไม่ได้ใช้ URL แบบ #anchor-name จึงไม่รองรับความสามารถนี้
  • คลิกเข้ามาเพราะรำคาญลิงก์แองเคอร์/ลิงก์ถาวรของ Jira แต่กรณีนี้คล้ายกันแต่ก็ไม่เหมือนกัน

    • ไม่สามารถย้ายไปยังแองเคอร์ด้วยคีย์บอร์ดได้
    • มีคำถามถึงผู้เขียนว่า ทำไมถึงใช้ JS event listener กับองค์ประกอบที่ไม่โต้ตอบ แทนที่จะใช้ HTML element
  • การเพิ่ม padding ไว้ใต้เนื้อหาหลักของหน้าจะเหมาะกว่า

    • ช่วยแก้ปัญหาที่ส่วนท้ายของเนื้อหาถูกตรึงอยู่ที่ขอบล่างของ viewport
    • บนมือถือ margin ระดับ 90vh เหมาะสม และบนหน้าจอใหญ่ขึ้น 50vh กำลังดี
    • บนเดสก์ท็อป margin 90vh อาจดูแปลกตา
  • ในเบราว์เซอร์สมัยใหม่ สามารถใช้ text fragments เพื่อไฮไลต์ส่วนเฉพาะของหน้าได้

    • ใน Chrome แค่ไฮไลต์ข้อความแล้วคลิกขวาเลือก "คัดลอกลิงก์"
    • ใช้สิ่งนี้ทุกวันเพื่อเน้นข้อความบางช่วงแทนการใช้แองเคอร์
  • ยังสามารถอนุญาตให้มีสถานะ "ใช้งานอยู่" ได้หลายจุดพร้อมกัน

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

    • ดีไซน์ของเว็บไซต์บนมือถือดูน่าสนใจ และสื่อสารวิธีแก้ปัญหาได้ชัดเจน
    • รู้สึกสดใหม่ที่ได้อ่านบล็อกสายเทคนิคโดยไม่มีป๊อปอัปมากวน
  • บน Firefox เดสก์ท็อป "โซลูชันที่สวยงาม" กลับไฮไลต์ "ส่วนตรงกลาง"

    • แม้จะยังไม่ถึงท้ายหน้า ก็เห็นบทสรุปครบถ้วนแล้ว
    • คำตอบคือควรไฮไลต์แองเคอร์ทั้งหมดที่มองเห็นบนหน้าจอ
  • บทความเขียนได้สะอาด และดีไซน์บล็อกก็น่าสนใจกว่าอีก

    • แม้จะไม่ชอบการจัดวางแบบชิดขวา แต่การเปิดใช้งานแบบอินไลน์ในป๊อปอัปด้านซ้ายก็ดูเจ๋งมาก