09모션 줄임 판
같은 카드 뒤집기를 prefers-reduced-motion이 켜진 환경에서 재생하면 회전 대신 부드러운 교차 페이드로 바뀝니다. 이 항목은 그 전환을 직접 보여줍니다.
쓰임모션 민감 사용자를 위한 접근성 기본값, 설정에 따라 애니메이션을 낮추는 모든 카드
prefers-reduced-motionopacitytransition

<main class="stage">
<div class="rm-card is-demo">
<div class="rm-card__inner">
<div class="rm-card__face rm-card__face--front">FRONT</div>
<div class="rm-card__face rm-card__face--back">BACK</div>
</div>
<span class="rm-tag">reduced-motion</span>
</div>
</main>@use "../../../../site/static/demo-tokens" as *;
// ── 변수 3개 ──────────────────────────────────────────
$duration: $dur-enter;
$easing: $ease-out;
$color: $subject-blue;
@include stage($stage-ink);
.rm-card {
position: relative;
perspective: 700px;
width: 170px;
height: 108px;
display: flex;
flex-direction: column;
align-items: center;
gap: $sp-2;
}
.rm-card__inner {
position: relative;
width: 170px;
height: 92px;
transform-style: preserve-3d;
}
// 실제 사용 경로: 평소엔 3D 회전, reduced-motion 이 켜지면 회전을 끄고 교차 페이드만 남긴다 (BD5)
.rm-card:hover .rm-card__inner { transform: rotateY(180deg); transition: transform $dur-enter $ease-spring; }
.rm-card__face {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: $r-card;
backface-visibility: hidden;
font: 700 14px/1 -apple-system, "Segoe UI", sans-serif;
color: $subject-cream;
}
.rm-card__face--front { background: $subject-blue-deep; }
.rm-card__face--back { background: rgba(255, 255, 255, .14); transform: rotateY(180deg); }
.rm-tag {
font: 600 10px/1 -apple-system, sans-serif;
letter-spacing: .05em;
color: $subject-cream;
opacity: .6;
}
// 데모 루프: 이 항목은 reduced-motion 결과 자체를 보여준다 — 회전 대신 opacity 교차 페이드만 무한 재생
@keyframes rm-crossfade-front { 0% { opacity: 1; } 50% { opacity: 0; } 100% { opacity: 1; } }
@keyframes rm-crossfade-back { 0% { opacity: 0; } 50% { opacity: 1; } 100% { opacity: 0; } }
.rm-card.is-demo .rm-card__inner { transform: none; }
.rm-card.is-demo .rm-card__face--front { animation: rm-crossfade-front ($duration * 2.6) $easing infinite; backface-visibility: visible; transform: none; }
.rm-card.is-demo .rm-card__face--back { animation: rm-crossfade-back ($duration * 2.6) $easing infinite; backface-visibility: visible; transform: none; }
@media (prefers-reduced-motion: reduce) {
.rm-card:hover .rm-card__inner { transform: none; transition: none; }
.rm-card:hover .rm-card__face--front { opacity: 0; transition: opacity $dur-base $ease-out; }
.rm-card:hover .rm-card__face--back { opacity: 1; transform: none; transition: opacity $dur-base $ease-out; }
}html, body {
margin: 0;
overflow: hidden;
}
.stage {
box-sizing: border-box;
min-height: 100vh;
display: grid;
place-items: center;
margin: 0;
background: #17141a;
font-family: -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
padding: clamp(8px, 4vw, 24px);
}
.rm-card {
position: relative;
perspective: 700px;
width: 170px;
height: 108px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.rm-card__inner {
position: relative;
width: 170px;
height: 92px;
transform-style: preserve-3d;
}
.rm-card:hover .rm-card__inner {
transform: rotateY(180deg);
transition: transform 600ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.rm-card__face {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 16px;
backface-visibility: hidden;
font: 700 14px/1 -apple-system, "Segoe UI", sans-serif;
color: #fff7e6;
}
.rm-card__face--front {
background: #0a4fe8;
}
.rm-card__face--back {
background: rgba(255, 255, 255, 0.14);
transform: rotateY(180deg);
}
.rm-tag {
font: 600 10px/1 -apple-system, sans-serif;
letter-spacing: 0.05em;
color: #fff7e6;
opacity: 0.6;
}
@keyframes rm-crossfade-front {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes rm-crossfade-back {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
.rm-card.is-demo .rm-card__inner {
transform: none;
}
.rm-card.is-demo .rm-card__face--front {
animation: rm-crossfade-front 1560ms ease-out infinite;
backface-visibility: visible;
transform: none;
}
.rm-card.is-demo .rm-card__face--back {
animation: rm-crossfade-back 1560ms ease-out infinite;
backface-visibility: visible;
transform: none;
}
@media (prefers-reduced-motion: reduce) {
.rm-card:hover .rm-card__inner {
transform: none;
transition: none;
}
.rm-card:hover .rm-card__face--front {
opacity: 0;
transition: opacity 300ms ease-out;
}
.rm-card:hover .rm-card__face--back {
opacity: 1;
transform: none;
transition: opacity 300ms ease-out;
}
}import { CSSProperties } from "react";
import styles from "./ReducedMotionFlip.module.scss";
export interface ReducedMotionFlipProps {
duration?: string;
easing?: string;
front?: string;
back?: string;
}
// prefers-reduced-motion 이 켜진 사용자는 3D 회전 대신 opacity 교차 페이드만 받는다 (CSS @media 블록, JS 분기 없음)
export default function ReducedMotionFlip({
duration = "600ms",
easing = "ease-out",
front = "FRONT",
back = "BACK",
}: ReducedMotionFlipProps) {
const style = { "--duration": duration, "--easing": easing } as CSSProperties;
return (
<div className={styles.card} style={style}>
<div className={styles.inner}>
<div className={`${styles.face} ${styles.front}`}>{front}</div>
<div className={`${styles.face} ${styles.back}`}>{back}</div>
</div>
<span className={styles.tag}>reduced-motion</span>
</div>
);
}09 모션 줄임 판 — 측정 누적면적 10.497% · 움직인 프레임 20/23GODRICH 원작 · zip 에 SCSS·React 포함 · CSS 카드 뒤집기 애니메이션 9종 (복붙 20줄)
이 데모가 속한 글
CSS 카드 뒤집기 애니메이션 9종 (복붙 20줄)CSS 카드 뒤집기는 마우스를 올리거나 클릭했을 때 카드가 휙 돌아가거나 반으로 접히면서 반대쪽 내용을 보여주는 애니메이션입니다. 코드를 몰라도 아래 데모에 마우스를 올려보면 바로 무슨 효과인지 알 수 있습니다. 이 이 글의 데모 전부 보기


