엘리먼트를 안 보이게 하는 다양한 방식과 각각의 장단점

CSS에서 요소를 시각적으로 숨기는 여러 방법이 있으며, 각 방법마다 고유한 장단점이 있습니다. 특히 접근성 측면에서 큰 차이가 있습니다. 주요 방법들을 살펴보겠습니다:

1. display: none

.hidden {
  display: none;
}

장점:

  • 요소가 DOM에서 완전히 사라진 것처럼 동작 (레이아웃에서 공간 차지하지 않음)
  • 모든 브라우저에서 일관되게 작동
  • 자식 요소도 모두 함께 숨겨짐

단점:

  • 접근성 트리에서 요소가 제거됨 (스크린 리더가 읽지 못함)
  • JavaScript로 포커스를 받을 수 없음
  • 애니메이션/전환 효과 적용 불가
  • 숨겨진 콘텐츠가 SEO에 영향을 줄 수 있음

2. visibility: hidden

.invisible {
  visibility: hidden;
}

장점:

  • 레이아웃에서 공간은 그대로 유지됨
  • 자식 요소도 기본적으로 모두 숨겨짐
  • visibility: visible을 통해 자식 요소만 개별적으로 표시 가능

단점:

  • 접근성 트리에서 요소가 제외됨 (스크린 리더가 읽지 못함)
  • 포커스를 받을 수 없음
  • 요소가 공간을 계속 차지함

3. opacity: 0

.transparent {
  opacity: 0;
}

장점:

  • 레이아웃에서 공간 유지됨
  • 요소는 여전히 클릭 가능하고 포커스를 받을 수 있음
  • 애니메이션/전환 효과 적용 가능
  • 접근성 트리에 남아있음

단점:

  • 완전히 눈에 보이지 않더라도 여전히 상호작용 가능 (의도하지 않은 클릭 발생 가능)
  • 공간을 계속 차지함
  • pointer-events: none을 추가로 적용하면 클릭은 방지할 수 있지만, 포커스는 여전히 가능

4. opacity: 0 + pointer-events: none

.transparent-no-interaction {
  opacity: 0;
  pointer-events: none;
}

장점:

  • 레이아웃에서 공간 유지됨
  • 마우스 이벤트(클릭 등)는 차단됨
  • 애니메이션/전환 효과 적용 가능

단점:

  • 키보드 포커스가 여전히 가능할 수 있음 (브라우저에 따라 다름)
  • 공간을 계속 차지함
  • 접근성 측면에서 혼란스러울 수 있음

5. CSS 위치 활용 (position: absolute + 화면 밖으로 이동)

.offscreen {
  position: absolute;
  left: -9999px;
  top: -9999px;
}

장점:

  • 레이아웃에 영향을 주지 않음
  • 접근성 트리에 남아있음 (스크린 리더가 읽을 수 있음)
  • 포커스를 받을 수 있음

단점:

  • 대형 웹사이트에서 많은 요소에 사용하면 렌더링 성능에 영향을 줄 수 있음
  • 좌표 값이 매우 큰 경우 스크롤 이슈가 발생할 수 있음

6. 스크린 리더용 숨김(권장 접근성 패턴)

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

장점:

  • 시각적으로는 보이지 않지만 스크린 리더는 접근 가능
  • 레이아웃에 영향을 주지 않음
  • 접근성 유지하면서 시각적으로 숨김

단점:

  • 시각적으로 완전히 숨기는 용도로만 사용해야 함 (일반 사용자에게 보여질 내용에는 부적합)
  • 다수의 CSS 속성 필요

7. HTML hidden 속성

<div hidden>내용</div>

장점:

  • 간단하고 명확한 문법
  • display: none과 동일한 효과
  • 시맨틱하게 "이 요소는 현재 관련이 없다"는 의미 전달

단점:

  • display: none과 동일한 접근성 문제
  • JavaScript로 조작해야 할 때 추가 작업 필요

이 방법들을 접근성 측면에서 비교

  1. 탭 포커스 가능여부:
    • opacity: 0
    • ✅ CSS 위치 활용
    • ✅ 스크린 리더용 숨김
    • display: none
    • visibility: hidden
    • ⚠️ opacity: 0 + pointer-events: none (브라우저별 차이)
  2. 스크린 리더 접근 가능여부:
    • opacity: 0
    • ✅ CSS 위치 활용
    • ✅ 스크린 리더용 숨김
    • display: none
    • visibility: hidden
    • opacity: 0 + pointer-events: none
  3. 공간 차지여부:
    • display: none (차지하지 않음)
    • visibility: hidden (여전히 차지)
    • opacity: 0 (여전히 차지)
    • opacity: 0 + pointer-events: none (여전히 차지)
    • ✅ CSS 위치 활용 (레이아웃에서 제외)
    • ✅ 스크린 리더용 숨김 (레이아웃에서 제외)

상황별 권장 사용 방법

  1. 일시적으로 요소를 숨겼다가 보여주는 UI 컴포넌트 (탭, 아코디언, 드롭다운 등):
    • opacity: 0 + 선택적으로 transform 조합 (애니메이션 가능)
  2. 접근성이 중요한 요소(스크린 리더가 읽어야 하는데 시각적으로는 숨기고 싶은 경우):
    • .sr-only 클래스 사용
  3. 완전히 숨기고 상호작용도 방지하고 싶은 경우:
    • display: none 또는 HTML hidden 속성
  4. 자리는 유지하면서 시각적으로만 숨기려는 경우:
    • visibility: hidden 또는 opacity: 0 + pointer-events: none
  5. 이미지 갤러리 등에서 이전/다음 버튼 처리:
    • 호버 시에만 나타나게: opacity: 0 + :hoveropacity: 1
    • 키보드 사용자도 고려: 포커스 시에도 표시 (opacity: 0 + :focus-withinopacity: 1)

지금의 이미지 뷰어 컴포넌트에서는 버튼을 숨기려면 opacity: 0를 사용하되, 포커스는 여전히 받을 수 있도록 하고, :focus 또는 :focus-visible 상태에서 opacity: 1로 변경하는 것이 가장 좋은 접근법입니다.

+ Recent posts