เน้นสไตล์

ตัวบ่งชี้โฟกัส (มักแสดงด้วย "วงแหวนโฟกัส") จะระบุองค์ประกอบที่โฟกัสอยู่ในขณะนี้ในหน้าเว็บ สำหรับผู้ใช้ที่ใช้เมาส์ไม่ได้ ตัวบ่งชี้นี้สำคัญอย่างยิ่งเนื่องจากทำหน้าที่แทนเคอร์เซอร์เมาส์

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

ระบบจะใช้คลาสจำลอง :focus ทุกครั้งที่มีโฟกัสองค์ประกอบ ไม่ว่าจะใช้อุปกรณ์อินพุต (เมาส์ แป้นพิมพ์ สไตลัส ฯลฯ) หรือวิธีการใดก็ตามในการโฟกัส ตัวอย่างเช่น <div> ด้านล่างมี tabindex ซึ่งทำให้โฟกัสได้ และมีสไตล์ที่กําหนดเองสําหรับสถานะ :focus ด้วย

div[tabindex="0"]:focus {
  outline: 4px dashed orange;
}

ไม่ว่าคุณจะใช้เมาส์คลิกหรือใช้แป้นพิมพ์กด Tab <div> จะเหมือนเดิมเสมอ

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

ตัวอย่างเช่น <button> ด้านล่างยังมีสไตล์ที่กำหนดเองสำหรับ:focusสถานะด้วย

button:focus {
  outline: 4px dashed orange;
}

หากคลิก <button> ด้วยเมาส์ใน Chrome บน macOS คุณควรเห็นสไตล์โฟกัสที่กำหนดเอง อย่างไรก็ตาม คุณจะไม่เห็นโหมดโฟกัสที่กำหนดเองหากคลิก <button> ใน Safari บน macOS เนื่องจากใน Safari องค์ประกอบจะไม่ได้รับการโฟกัสเมื่อคุณคลิก

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

ใช้ :focus-visible เพื่อแสดงสัญญาณบอกสถานะโฟกัสแบบเลือก

ระบบจะใช้คลาสที่ไม่ระบุจริง :focus-visible ใหม่ทุกครั้งที่เอลิเมนต์ได้รับโฟกัส และเบราว์เซอร์จะพิจารณาผ่านวิธีการหาค่าประมาณว่าการแสดงตัวบ่งชี้โฟกัสจะเป็นประโยชน์ต่อผู้ใช้หรือไม่ โดยเฉพาะอย่างยิ่ง หากการโต้ตอบล่าสุดของผู้ใช้ผ่านแป้นพิมพ์และการกดแป้นไม่ได้รวมแป้นเมตา ALT / OPTION หรือ CONTROL :focus-visible จะจับคู่

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

button:focus-visible {
  outline: 4px dashed orange;
}

ใช้ :focus-within เพื่อจัดสไตล์องค์ประกอบหลักขององค์ประกอบที่โฟกัส

ระบบจะใช้คลาสจำลอง :focus-within กับองค์ประกอบเมื่อองค์ประกอบนั้นได้รับโฟกัสหรือเมื่อองค์ประกอบอื่นภายในองค์ประกอบนั้นได้รับโฟกัส

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

form:focus-within {
  background: #ffecb3;
}

กรณีที่ควรแสดงตัวบ่งชี้โฟกัส

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

หากคำตอบคือ "ใช่" การควบคุมควรแสดงตัวบ่งชี้โฟกัสอยู่เสมอ ไม่ว่าอุปกรณ์อินพุตที่ใช้โฟกัสจะเป็นอุปกรณ์ใดก็ตาม ตัวอย่างที่ดีคือเอลิเมนต์ <input type="text"> ผู้ใช้จะต้องส่งอินพุตไปยังองค์ประกอบผ่านแป้นพิมพ์ ไม่ว่าองค์ประกอบอินพุตจะได้รับโฟกัสในตอนแรกอย่างไร ดังนั้นการแสดงตัวบ่งชี้โฟกัสเสมอจึงมีประโยชน์

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

หลีกเลี่ยง outline: none

วิธีที่เบราว์เซอร์ตัดสินใจว่าจะวาดตัวบอกโฟกัสเมื่อใดนั้นค่อนข้างสับสน การเปลี่ยนลักษณะที่ปรากฏขององค์ประกอบ <button> ด้วย CSS หรือการให้องค์ประกอบ tabindex จะทําให้ลักษณะการทํางานของวงแหวนโฟกัสเริ่มต้นของเบราว์เซอร์เริ่มทํางาน

รูปแบบที่ไม่เหมาะสมที่พบบ่อยมากคือการนําตัวบ่งชี้โฟกัสออกโดยใช้ CSS เช่น

/* Don't do this!!! */
:focus {
  outline: none;
}

วิธีแก้ปัญหาที่ดีกว่าคือการใช้ :focus ร่วมกับ :focus-visible polyfill บล็อกโค้ดแรกด้านล่างแสดงวิธีการทำงานของ polyfill และแอปตัวอย่างด้านล่างแสดงตัวอย่างการใช้ polyfill เพื่อเปลี่ยนตัวบ่งชี้โฟกัสบนปุ่ม

/*
  This will hide the focus indicator if the element receives focus via the
  mouse, but it will still show up on keyboard focus.
*/
.js-focus-visible :focus:not(.focus-visible) {
  outline: none;
}

/*
  Optionally: Define a strong focus indicator for keyboard focus.
  If you choose to skip this step, then the browser's default focus
  indicator will be displayed instead.
*/
.js-focus-visible .focus-visible {
  
}