Accessibility Wiki

커뮤니티 위키 & 포럼

카테고리

프론트엔드 개발

최근 수정

2024년 1월

기여자

활성 기여자 42명

관련 주제

HTMLJavaScriptWeb Design

Build inclusive web experiences for everyone

Semantic HTML

Use semantic HTML elements to provide meaning and structure to your content for screen readers and assistive technologies.

<!-- Bad: Non-semantic -->
<div class="header">
  <div class="nav">
    <div class="nav-item">Home</div>
  </div>
</div>

<!-- Good: Semantic -->
<header>
  <nav>
    <a href="/">Home</a>
  </nav>
</header>

<main>
  <article>
    <h1>Article Title</h1>
    <p>Article content...</p>
  </article>
</main>

<footer>
  <p>&copy; 2025 Site Name</p>
</footer>

ARIA Attributes

Use ARIA attributes to enhance accessibility when semantic HTML isn't enough.

<!-- Button with ARIA label -->
<button aria-label="Close dialog" onClick={closeDialog}>
  <X className="icon" aria-hidden="true" />
</button>

<!-- Custom dropdown -->
<div role="listbox" aria-label="Select option">
  <div role="option" aria-selected="true">Option 1</div>
  <div role="option" aria-selected="false">Option 2</div>
</div>

<!-- Loading state -->
<div aria-live="polite" aria-busy="true">
  Loading content...
</div>

<!-- Form with error -->
<input
  type="email"
  aria-label="Email address"
  aria-invalid="true"
  aria-describedby="email-error"
/>
<span id="email-error" role="alert">
  Please enter a valid email
</span>

Keyboard Navigation

Ensure all interactive elements are keyboard accessible and have visible focus states.

/* Visible focus indicators */
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Skip to main content link */
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: var(--primary);
  color: white;
  padding: 8px;
  text-decoration: none;
}

.skip-link:focus {
  top: 0;
}

/* Keyboard trap for modals */
function Modal({ onClose, children }) {
  const modalRef = useRef(null);
  
  useEffect(() => {
    const focusableElements = modalRef.current.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    );
    const firstElement = focusableElements[0];
    const lastElement = focusableElements[focusableElements.length - 1];
    
    firstElement?.focus();
    
    const trapFocus = (e) => {
      if (e.key === 'Tab') {
        if (e.shiftKey && document.activeElement === firstElement) {
          lastElement?.focus();
          e.preventDefault();
        } else if (!e.shiftKey && document.activeElement === lastElement) {
          firstElement?.focus();
          e.preventDefault();
        }
      }
    };
    
    document.addEventListener('keydown', trapFocus);
    return () => document.removeEventListener('keydown', trapFocus);
  }, []);
  
  return <div ref={modalRef} role="dialog">{children}</div>;
}

토론 (0)

내 아바타

의견을 남겨 주세요

아직 댓글이 없습니다. 첫 번째 토론을 시작해 보세요!