노트

prefers-reduced-motion(동작 줄이기)

prefers-reduced-motion

프런트엔드#css#browser · 연결된 개념 3개

쉽게 말하면

prefers-reduced-motion은 사용자가 휴대폰이나 컴퓨터 설정에 '움직이는 화면은 어지러워요'라고 적어 둔 메모를 웹페이지가 읽는 방법이에요. 이 신호가 오면 크게 움직이는 애니메이션을 줄이거나 바꿔요.

비유가 깨지는 곳 'reduce'는 전부 끄라는 뜻이 아니에요. 상태 변화를 알려 주던 전환은 위치 이동 대신 페이드로 바꿔 남기고, 폭죽 같은 순수 장식은 꺼도 잃는 정보가 없어요.

prefers-reduced-motion은 사용자가 운영체제에서 화면 움직임을 줄여 달라고 설정했는지 알려 주는 CSS 미디어 기능(media feature)이다. 값은 no-preference와 reduce 두 가지다. 확대·축소, 패럴랙스, 큰 요소가 화면을 가로지르는 움직임은 전정기관 장애가 있는 사람에게 어지럼증과 메스꺼움을 일으킬 수 있어서 있는 설정이다. 2020년부터 주요 브라우저가 모두 지원한다.

어디서 켜나 (2026 기준)

  • macOS: 시스템 설정 → 손쉬운 사용 → 동작(Tahoe부터. 그 전에는 디스플레이) → 동작 줄이기
  • iOS: 설정 → 손쉬운 사용 → 동작
  • Windows 11: 설정 → 접근성 → 시각 효과 → 애니메이션 효과
  • Android: 설정 → 접근성 → 애니메이션 삭제

쓰는 법

.card {
  transition: transform 300ms ease;
}
 
@media (prefers-reduced-motion: reduce) {
  .card {
    transition: opacity 200ms ease; /* 움직임 대신 서서히 나타나기 */
  }
}

JS(JavaScript)로 띄우는 애니메이션은 matchMedia로 확인한다. 라이브러리를 동적으로 불러오는 연출이라면, 설정이 켜져 있을 때 import 자체를 건너뛰어 불필요한 다운로드도 막을 수 있다.

const reduce = window.matchMedia('(prefers-reduced-motion: reduce)')
if (!reduce.matches) {
  const { default: confetti } = await import('canvas-confetti')
  confetti()
}
reduce.addEventListener('change', (e) => { /* 실행 중에 설정이 바뀔 때 */ })

없애기보다 줄이기

"reduce"는 "전부 끄라"가 아니다. 위치·크기가 바뀌는 움직임을 페이드나 색 변화로 바꾸거나, 길이를 줄이거나, 자동 재생을 멈추는 쪽이 낫다. 상태 변화를 알려 주던 전환을 통째로 지우면 무슨 일이 일어났는지 알 수 없게 될 수 있다. 반대로 순수한 장식(폭죽, 배경 파티클)은 꺼도 잃는 정보가 없다.

WCAG 기준

  • 2.3.3 Animation from Interactions (AAA): 상호작용이 일으키는 움직임 애니메이션은 꺼질 수 있어야 한다. 단, 기능이나 정보 전달에 꼭 필요한 애니메이션은 예외다. 색·투명도·흐림만 바뀌는 건 크기·모양·위치가 달라 보이지 않는 한 "움직임"에 들지 않는다. prefers-reduced-motion을 쓰는 것이 이 기준을 맞추는 대표 기법(C39, SCR40)이다
  • 2.2.2 Pause, Stop, Hide (A): 자동으로 시작해 5초 넘게 움직이는 콘텐츠는 멈추거나 숨길 수 있어야 한다. 사용자의 조작이 아니라 페이지가 스스로 시작하는 움직임에 관한 기준이다

테스트

  • Chrome DevTools: Rendering 패널 → Emulate CSS media feature prefers-reduced-motion → reduce(크롬 개발자 도구 팁)
  • Playwright: await page.emulateMedia({ reducedMotion: 'reduce' })를 걸고, 애니메이션 요소가 생기지 않는지와 관련 청크 요청이 없는지를 확인하는 회귀 테스트를 만들 수 있다

움직임 자체를 가볍게 만드는 법은 합성 단계와 transform·opacity과 requestAnimationFrame을 본다.

출처: MDN — prefers-reduced-motion · W3C — Understanding SC 2.3.3 Animation from Interactions · Chrome DevTools — Emulate CSS media features · Playwright — page.emulateMedia

연결된 개념

이 노트를 가리키는 문서

아직 없습니다.

뜻이 가까운 노트

  • Activity와 숨겨진 라우트 보존

    Activity는 React 19.2의 컴포넌트로, UI를 언마운트하지 않고 display: none으로 숨기면서 state와 DOM(Document Object Model)을 보존한다. 숨기는 동안 Effect는 정리(cleanup)된다. 예전 이름은 Offscreen이다.

  • 반응형 웹 디자인

    하나의 페이지가 화면 크기와 기기에 맞춰 레이아웃·이미지·글자 크기를 바꾸도록 만드는 접근. 미디어 쿼리(Media Query), 유연한 레이아웃(Flexible Layout), 반응형 미디어(Responsive Media)가 세 축이다.

  • 내부 가변성과 메모이제이션

    내부 가변성(Interior Mutability)은 객체나 함수의 참조는 그대로인데 안에 숨은 상태가 바뀌는 성질이다. React의 메모이제이션은 "입력이 다른 참조인가"만 보기 때문에, 참조가 같으면 내용이 바뀌어도 바뀌지 않았다고 판단한다. React 공식 문서는 이를 "겉모습은 같은데 몰래 내용물을 바꾸는 상자"에 비유한다.

  • content-visibility

    화면 밖에 있는 요소의 렌더링을 건너뛰어도 된다고 브라우저에 알려 주는 CSS 속성. auto를 주면 뷰포트에서 멀리 있는 요소의 레이아웃·페인트를 생략하므로, 긴 페이지의 첫 렌더링과 스크롤이 빨라진다.

  • 상태 내리기와 컴포지션으로 리렌더 줄이기

    상태 내리기(State Colocation)는 state를 실제로 쓰는 컴포넌트 가까이로 옮겨, state가 바뀔 때 다시 렌더되는 범위를 좁히는 기법이다. 메모이제이션(Memoization)보다 먼저 시도할 구조적 최적화다.

보기 옵션