아코디언, 탭, 스크롤에 따라 나타나는 요소 — 예전에는 전부 스크립트가 하던 일입니다. 지금은 상당수가 스타일시트 안에서 끝납니다. 스크립트를 줄이면 요청과 실행 시간이 줄고, 무엇보다 스크립트가 실패했을 때 화면이 죽지 않습니다.
다만 새 기능일수록 브라우저 지원이 고르지 않습니다. 그래서 기법보다 먼저 정해야 할 규칙이 하나 있습니다.
규칙 — 기본값이 완성된 상태여야 합니다
이 한 줄이 CSS 상호작용을 안전하게 만드는 전부입니다. 아무 기능도 지원되지 않는 브라우저가 받는 화면이 “빈 자리” 가 아니라 “완성된 정적 화면” 이어야 한다는 뜻입니다.
반대로 하면 어떻게 되는지가 중요합니다. 요소를 opacity: 0 으로 숨겨 두고 스크롤 애니메이션이 그것을 1로 올리게 만들면, 그 애니메이션을 지원하지 않는 브라우저에서는 콘텐츠가 영영 나타나지 않습니다. 화면은 200 을 돌려주고 마크업도 멀쩡한데 사람 눈에는 빈 구역만 보입니다 — 발견이 가장 늦는 종류의 고장입니다.
구현에서는 지원 여부 질의(@supports)와 모션 축소 질의 안에만 애니메이션 선언을 두는 형태가 됩니다. 이 사이트의 스크롤 효과도 전부 그렇게 되어 있습니다 — 지원하지 않는 브라우저에서 이 페이지를 열면 움직임만 없고 내용은 그대로 보입니다.
실제로 쓸 수 있는 다섯 가지
1. <details> — 아코디언과 FAQ. 열고 닫기가 브라우저 기본 기능이라 키보드 조작과 보조기기 대응이 처음부터 됩니다. 검색 · 인쇄에서 내용이 문서 안에 그대로 있다는 점도 중요합니다. 스크립트로 만든 아코디언은 닫힌 내용을 DOM 에서 빼 버리는 경우가 있어 그 부분이 검색되지 않습니다.
2. :target — 주소로 여는 화면. 링크가 가리키는 요소에만 규칙이 걸리므로 각주 강조, 단순 탭, 모달 비슷한 화면을 스크립트 없이 만들 수 있습니다. 상태가 주소에 남는 것이 장점이자 한계입니다 — 공유하면 그 상태 그대로 열리지만, 뒤로가기가 그 상태를 되짚습니다.
3. :focus-within — 내부 포커스를 부모가 안다. 검색창에 커서가 들어갔을 때 전체 검색 박스를 강조하는 식입니다. 마우스뿐 아니라 키보드 사용자에게도 같은 피드백이 간다는 점이 이 선택자의 진짜 값입니다.
4. :has() — 조건을 부모로 올린다. “이미지가 없는 카드는 레이아웃을 다르게”, “체크된 항목이 있는 목록은 도구 막대를 보이게” 같은 규칙이 스타일시트에서 끝납니다. 종전에는 서버나 스크립트가 클래스를 붙여 주어야 했던 일입니다.
5. 스크롤 연동 애니메이션. 진행 바, 요소 진입 시 페이드, 절차 레일 그리기 같은 효과를 스크롤 이벤트 없이 만듭니다. 스크롤할 때마다 스크립트가 위치를 읽는 구조를 없앨 수 있어 스크롤 자체가 가벼워집니다.
/* 기본값 = 최종 상태. 여기까지가 모든 브라우저가 받는 화면 */
.reveal { opacity: 1; translate: 0 0; }
/* 지원하고, 사용자가 모션을 원할 때만 움직임을 얹는다 */
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.reveal {
animation: reveal-in linear both;
animation-timeline: view();
animation-range: entry 10% cover 35%;
}
}
}
@keyframes reveal-in {
from { opacity: 0; translate: 0 16px; }
to { opacity: 1; translate: 0 0; }
}
위 예시에서 transform 이 아니라 translate 속성을 쓴 것에는 이유가 있습니다. 채워진 애니메이션의 transform 은 카드 호버의 transform 을 덮어써서, 진입 애니메이션이 걸린 카드만 호버가 죽는 상황이 생깁니다. 두 속성이 분리돼 있으므로 하나는 애니메이션이, 하나는 호버가 쓰면 서로 간섭하지 않습니다.
여기서 멈춰야 하는 지점
모든 것을 CSS 로 밀어붙이면 오히려 나빠집니다. 경계는 접근성 계약에서 갈립니다.
특히 숨은 체크박스 기법은 주의합니다. 눈에 보이는 것은 탭이나 토글인데 실제 요소는 체크박스라, 낭독기 사용자에게는 “체크박스” 라고 안내됩니다. 시각적으로는 완벽하게 동작하면서 의미 계층만 어긋나는 상태이고, 이것은 눈으로 하는 검수에서 절대 발견되지 않습니다.
기준은 간단합니다. 보이는 것과 알려지는 것이 어긋나기 시작하면 그 지점이 멈출 자리입니다. 그 앞까지는 CSS 가 스크립트보다 튼튼하고, 그 뒤로는 제대로 만든 스크립트가 필요합니다.
포커스 · 낭독기 · 키보드 조작을 순서대로 갖추는 방법은 접근성 연재에 정리돼 있고, 스크립트 무게가 성능에 미치는 영향은 성능 최적화 아카이브에서 다룹니다. 실제 사이트에서 무엇을 걷어낼 수 있는지 진단부터 받고 싶다면 최적화 지원 사업을 참고하세요.