- 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 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ในฐานะนักพัฒนาแบ็กเอนด์ เวลาเห็นงานฝั่งฟรอนต์เอนด์บางครั้งก็รู้สึกทึ่งกับความซับซ้อน
ตั้งคำถามถึงเป้าหมายด้าน UX ของการแสดง "แองเคอร์ที่กำลังใช้งาน" ในเมนูนำทางด้านข้าง
ฟังก์ชัน UX ที่สำคัญที่สุดของลิงก์แองเคอร์คือควรส่งให้คนอื่นได้และบันทึกเป็นบุ๊กมาร์กได้
คลิกเข้ามาเพราะรำคาญลิงก์แองเคอร์/ลิงก์ถาวรของ Jira แต่กรณีนี้คล้ายกันแต่ก็ไม่เหมือนกัน
การเพิ่ม padding ไว้ใต้เนื้อหาหลักของหน้าจะเหมาะกว่า
ในเบราว์เซอร์สมัยใหม่ สามารถใช้ text fragments เพื่อไฮไลต์ส่วนเฉพาะของหน้าได้
ยังสามารถอนุญาตให้มีสถานะ "ใช้งานอยู่" ได้หลายจุดพร้อมกัน
การได้อ่านคอมเมนต์อื่น ๆ ก็สนุกดี
บน Firefox เดสก์ท็อป "โซลูชันที่สวยงาม" กลับไฮไลต์ "ส่วนตรงกลาง"
บทความเขียนได้สะอาด และดีไซน์บล็อกก็น่าสนใจกว่าอีก