- ในเว็บอินเทอร์เฟซ การใช้
<button> แทน <div> คือทางเลือกที่ถูกต้องกว่า ทั้งในแง่การเข้าถึงและการทำงาน
<div> ไม่ถูกโปรแกรมอ่านหน้าจอมองว่าเป็นองค์ประกอบที่โต้ตอบได้ และไม่ตอบสนองต่อการโฟกัสด้วยคีย์บอร์ดหรือการกด Enter, Spacebar
- แม้จะเพิ่มแอตทริบิวต์
[role="button"] หรือ [tabindex="0"] ก็ยังมี ปัญหาเรื่องลำดับการโฟกัสและการจัดการอีเวนต์จากคีย์บอร์ด อยู่
- การแก้ปัญหาเหล่านี้ด้วยการ เพิ่ม event listener และเงื่อนไขจำนวนมาก ทำให้เกิดความซับซ้อนที่ไม่จำเป็น
<button> มีการรองรับการเข้าถึง การโฟกัส และการจัดการอินพุตจากคีย์บอร์ดมาให้โดยอัตโนมัติ จึงเป็นทางออกที่เรียบง่ายและเป็นมาตรฐาน
แนวทางที่ผิด: สร้างปุ่มด้วย <div>
- ในหมู่ผู้ใช้ React หรือ HTMX มักพบการเขียน
<div onclick="..."> เพื่อ ทำอินเทอร์แอ็กชันอย่างการเปิดโมดัล
- ปัญหาของวิธีนี้
- โปรแกรมอ่านหน้าจอ ไม่รับรู้องค์ประกอบนี้ว่าเป็นองค์ประกอบแบบโต้ตอบได้
- ไม่สามารถย้ายโฟกัสมาที่องค์ประกอบนี้ด้วยคีย์บอร์ดได้
- มีเพียงอีเวนต์
click ที่ทำงาน และ ไม่ตอบสนองต่อการกด Enter หรือ Spacebar
ข้อจำกัดของความพยายามในการ “แก้” เรื่องการเข้าถึง
ฟีเจอร์พื้นฐานที่ <button> มีให้
บทสรุป: ความเรียบง่ายคือสิ่งที่ดีที่สุด
<button> คือ วิธีที่เรียบง่ายที่สุดในการรองรับมาตรฐานการเข้าถึง พร้อมกับลดปริมาณโค้ด
- การ ใช้องค์ประกอบ HTML มาตรฐาน โดยไม่เพิ่มการจัดการอีเวนต์หรือแอตทริบิวต์ที่ไม่จำเป็น จะดีกว่าในแง่การบำรุงรักษาและประสิทธิภาพ
- ข้อความสำคัญคือ “ยิ่งเป็นนักพัฒนาที่ขี้เกียจ ก็ยิ่งควรใช้องค์ประกอบให้ถูกต้อง”
โดย เน้นความสำคัญของนิสัยการพัฒนาที่หลีกเลี่ยงความซับซ้อนที่ไม่จำเป็น และใช้ประโยชน์จากความสามารถพื้นฐานที่มีอยู่แล้ว
7 ความคิดเห็น
เป็นบทความที่ดีมากครับ ใจความสำคัญของเนื้อหาสามารถสรุปได้ว่า "เราควรใช้แท็ก HTML อย่างมีความหมาย" หากให้
div(หรือแท็กอื่น) ทำหน้าที่รองรับเหตุการณ์คลิก ผมคิดว่ามันก็ไม่ได้ต่างอะไรจากสมัยก่อนที่เราใช้แท็กtableจัดเลย์เอาต์เลยแน่นอนว่าใส่พร็อพเพอร์ตี
aria-*ลงไปก็อาจทำให้ชัดเจนขึ้นได้ แต่ถ้าต้องลำบากขนาดนั้นก็ใช้แท็กที่เหมาะสมไปเลยดีกว่า 555555คิดถึงจังเลย 555
เว็บไซต์หน่วยงานราชการบ้านเราดูเหมือนจะใช้
<a>กันเยอะมาก...ความเห็นจาก Hacker News
หนึ่งในเรื่องที่ฉันไม่ชอบคือเว็บไซต์ที่ทำ navigation ด้วย ตัวจัดการ
onclickแค่ใช้แท็ก
<a>ทุกอย่างก็ทำงานได้ดีเองโดยอัตโนมัติ ทั้งการเปิดแท็บใหม่ การทำงานร่วมกับอุปกรณ์ช่วยการเข้าถึง เมนูคลิกขวา ฯลฯถ้าเป็น navigation ก็ควรใช้ลิงก์แทน JavaScript soup
น่าจะเป็นเพราะอิทธิพลของเฟรมเวิร์กหรือไม่ก็ความไม่ใส่ใจ
ถึงอย่างนั้น วิธีดั้งเดิม ก็แทบจะดีกว่าในแง่ UX เสมอ
ฉันหวังว่าคนที่พยายามมาแทนที่แท็ก
<a>จะเจอกับความไม่สะดวกเล็กน้อยบ้างคนพวกนี้สร้างแพตเทิร์นที่ผิดไว้ แล้วนักพัฒนารุ่นถัดมาก็ทำตามกันต่อ
แทบไม่มีกรณีไหนเลยที่จำเป็นต้องแต่ง
<div>ให้เป็นปุ่มฉันใช้ปุ่มกลางเมาส์เพื่อเลื่อนบ่อยมาก แต่หลายเว็บทำให้มันพัง
ถ้าคลิกซ้ายจะพาไปหน้าตรวจสอบความปลอดภัย แต่ถ้าคลิกกลางจะเข้าไปปลายทางเลย
onClickแม้แต่องค์ประกอบที่จริง ๆ แล้วก็คือลิงก์ก็ยังถูกจัดการด้วย click handler ทั้งหมด เลยไม่เข้าใจจริง ๆ
ปุ่มส่วนใหญ่ควรระบุ
type="button"ให้ชัดเจนค่าเริ่มต้นคือ
submitดังนั้นถ้าอยู่ในฟอร์มก็จะ submit อัตโนมัติน่าจะมีนักพัฒนาบางคนไม่รู้เรื่องนี้เลยใช้
<div>แทนปุ่มที่ใช้ type เริ่มต้นมีพฤติกรรมแปลก ๆ และบางครั้งก็ข้าม JS handler ไปเลย
<input type="submit">และต่างจาก<button><div>ก็หลีกเลี่ยงปัญหาtype="submit"ได้<div>ว่างเปล่ามาตั้งแต่ต้น จึงใส่เฉพาะความสามารถที่ต้องการได้ และแก้ทีหลังก็ง่ายในทางกลับกัน
<button>ถ้าจะเข้าใจพฤติกรรมเริ่มต้นก็ต้องไปเปิดเอกสารดูสุดท้ายแล้วมันคือทางเลือกระหว่าง การควบคุมแบบ explicit กับความสามารถที่มีมาในตัว
อยากให้บทความขยายไปในทิศทางของ “ใช้ element HTML ที่สร้างมาเพื่อจุดประสงค์นั้นไปเลย”
นักพัฒนา SPA จำนวนมากไม่ค่อยเข้าใจความหมายของ element HTML เลยสร้างล้อขึ้นมาใหม่ทุกครั้ง
อย่างเช่น date picker เริ่มต้นนั้นหน้าตาแย่มากจนต้องเอาแบบอิง JS มาแทน
นั่นจึงเป็นที่มาของปุ่มแบบ custom
ทุกวันนี้มีคนรุ่นหนึ่งที่ต้องคอยกดไปทั่วหน้าจอเพื่อหาว่าตรงไหนคลิกได้
เมื่อ 10 ปีก่อนมีใครบางคนทำให้ การลากลิงก์ สำคัญกว่าการเลือกข้อความ จนตอนนี้แทบจะเลือกข้อความไม่ได้เลย
ถ้าจะซ่อมเรื่องนี้อาจต้อง fork เบราว์เซอร์
ถ้ากด Alt (หรือ Option) ค้างไว้ ก็จะเลือกข้อความในลิงก์ได้
เป็นพฤติกรรมที่ไม่ต้องการจริง ๆ
ถ้าใช้แอป TextSniper บน macOS จะเลือกพื้นที่แล้ว OCR เพื่อคัดลอกข้อความได้
เลยทำให้ Google Analytics พอใช้งานได้ขึ้นมาหน่อย
ปัญหาแบบนี้ควรถูกพูดถึงให้บ่อยกว่านี้
เมื่อก่อนชื่อ Select Like A Boss ตอนนี้ชื่อ Drag-Select Link Text
ใน stylesheet เริ่มต้นของ Chrome มี
button {align-items: flex-start}อยู่ ทำให้ฉันงงกับ บั๊กขนาด flexbox อยู่นานมากถึงอย่างนั้นก็ยังพยายามใช้ element HTML ที่ถูกต้องเท่าที่ทำได้ แต่ใน side project เล็ก ๆ บางครั้ง
<div>ก็สะดวกกว่าappearance: noneมีประโยชน์มากสำหรับรีเซ็ตสไตล์ปุ่มฉันสร้างคลาส
.unbuttonifyไว้เพื่อให้มันทำงานเหมือนปุ่มแต่หน้าตาเป็นอย่างอื่นควรใช้ element ต่าง ๆ ให้ตรงกับเจตนาเดิมของมัน ให้มากที่สุด
ฉันมีข้อบ่นเกี่ยวกับปุ่มอยู่สองอย่าง
อย่างหนึ่งคือสุดท้ายแล้วก็ต้อง จัดสไตล์ใหม่อยู่ดี
อีกอย่างคือคำเตือนว่าห้ามซ้อนปุ่มกัน
ในทางปฏิบัติมันเจอบ่อยพอสมควร
LLM มักสร้าง แพตเทิร์นที่ผิด แบบนี้บ่อย
หลายครั้งมันมองข้ามความสามารถพื้นฐานของเบราว์เซอร์แล้วไปทำให้ซับซ้อน
ฉันมักสั่ง Claude ให้ทำโค้ดแบบนี้ให้ง่ายลง
ใน TypeScript มันก็มีแนวโน้มจะทำรูปแบบการจัดการ error แปลก ๆ ด้วย
ฉันพยายาม ใช้ปุ่มเป็นค่าเริ่มต้น ให้มากที่สุด
แต่ถ้ากรณีไหนจริง ๆ แล้วควรทำงานเหมือนลิงก์ ก็จะใช้แท็ก
<a><a>ฉันสงสัยว่าทำไมถึงมีคนเสนอให้ใช้
<div><div>เอื้อต่อการ custom หน้าตา แบบแปลก ๆ มากกว่าเลยลงเอยด้วยสิ่งที่ทั้งไม่ดูเหมือนปุ่มและไม่ทำงานเหมือนปุ่ม
<div onclick>ใช้ปุ่มเถอะ
background, border, outline, appearance, -webkit-appearance, cursor
มีสไตล์ชีตเริ่มต้นที่ต้องเขียนทับเยอะเกินไปเลย ฮือๆ
ก็เลยมี CSS Reset ไงล่ะ