C
HTML/CSS/고급/Lesson 11

CSS 변수 · 애니메이션 — 현대 UI 의 필수 어휘

45분·theory

CSS 변수 · 애니메이션 — 현대 UI 의 필수 어휘

🎯 이 lesson 을 읽고 나면

이 lesson 을 다 읽고 나면 아래 3가지를 자신 있게 할 수 있습니다.

  • ✅ CSS Custom Properties (--var) 로 다크모드 구현
  • ✅ transition vs @keyframes 차이
  • ✅ prefers-reduced-motion 접근성 대응

학습 목표를 체크리스트로 두고 다 답할 수 있게 되면 lesson 을 닫으세요.

CSS 변수 (Custom Properties) — `--name`

기본 사용

css
:root {
    --primary: #00d066;
    --text-base: 16px;
    --radius: 8px;
}

.btn {
    background: var(--primary);
    border-radius: var(--radius);
    font-size: var(--text-base);
}

:root전역 스코프. 어디서든 var(--name) 으로 참조.

컴포넌트 스코프

css
.card {
    --card-padding: 16px;
    padding: var(--card-padding);
}
.card.large {
    --card-padding: 32px;        /* 같은 변수, 다른 값 */
}

요소별로 변수 재정의 가능. 부모에서 정의한 변수를 자식이 오버라이드.

다크모드 — 변수 하나만 바꾸면 끝

css
:root {
    --bg: #ffffff;
    --fg: #000000;
}
[data-theme="dark"] {
    --bg: #1a1a1a;
    --fg: #e6e6e6;
}

body {
    background: var(--bg);
    color: var(--fg);
}
javascript
// JS 로 테마 전환
document.documentElement.dataset.theme = 'dark';

수십 개 색상을 일일이 안 건드려도 테마 변경. Tailwind 의 dark: 변형이 이걸 자동화한 것.

prefers-color-scheme — 시스템 설정 따라가기

css
@media (prefers-color-scheme: dark) {
    :root {
        --bg: #1a1a1a;
        --fg: #e6e6e6;
    }
}

사용자 OS 설정 자동 감지. 강제 토글이 필요 없을 때.

JS 와의 연동

javascript
// 읽기
getComputedStyle(document.documentElement).getPropertyValue('--primary');

// 쓰기
document.documentElement.style.setProperty('--primary', '#ff0000');

Tailwind + CSS 변수

css
@theme {
    --color-primary: #00d066;
    --radius-card: 12px;
}

Tailwind v4 는 완전히 CSS 변수 기반. bg-primary 가 자동으로 bg: var(--color-primary) 가 됩니다.

transition — 부드러운 상태 전환

가장 단순

css
.btn {
    background: blue;
    transition: background 0.3s ease;
}
.btn:hover {
    background: red;     /* 0.3초에 걸쳐 부드럽게 */
}

속성 / 시간 / 타이밍 함수 세 가지가 transition 의 핵심.

여러 속성 동시에

css
.card {
    transform: translateY(0);
    box-shadow: 0 1px 2px rgba(0,0,0,0.1);
    transition: transform 0.3s, box-shadow 0.3s;
}
.card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 16px rgba(0,0,0,0.15);
}

카드 호버시 살짝 위로 + 그림자 진하게 — 모던 웹의 표준 패턴.

타이밍 함수

  • linear — 일정 속도
  • ease (기본) — 가속 후 감속
  • ease-in — 천천히 시작
  • ease-out — 빠르게 시작, 끝에 부드럽게 (UI 표준)
  • cubic-bezier(...) — 커스텀

UI 전환은 거의 ease-out. "빠른 시작 + 안착" 의 자연스러움.

transition: all 의 함정

css
.btn {
    transition: all 0.3s;   /* ❌ 모든 속성 — 성능 떨어짐 */
}

명시적으로 속성 나열 이 더 좋음:

css
.btn {
    transition: background-color 0.2s, transform 0.2s;
}

어떤 속성이 애니메이션 가능 한가

숫자로 보간 가능 한 것만. display, visibility, background-image불가. opacity, transform, color, width, height가능.

GPU 가속이 잘 되는 속성: transform, opacity (성능 압승). width/height 변경은 레이아웃 재계산 이라 느림.

transform — translate / scale / rotate

css
.el:hover {
    transform: translateX(20px) scale(1.05) rotate(5deg);
}

마진/패딩 변경보다 빠름 — GPU 가 직접 합성.

@keyframes — 복잡한 애니메이션

기본 구조

css
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(20px); }
    to   { opacity: 1; transform: translateY(0); }
}

.modal {
    animation: fadeIn 0.3s ease-out;
}

0% → 100% (from → to) 를 정의. CSS 가 알아서 보간.

중간 단계가 필요할 때

css
@keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-20px); }
}

.icon { animation: bounce 1s infinite; }

로딩 스피너 — 실전 예시

css
@keyframes spin {
    to { transform: rotate(360deg); }
}

.spinner {
    width: 24px;
    height: 24px;
    border: 3px solid #eee;
    border-top-color: #00d066;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

모든 SaaS 사이트가 쓰는 스피너 가 이거.

animation 속성 풀세트

css
.el {
    animation:
        fadeIn          /* 이름 */
        0.3s            /* duration */
        ease-out        /* timing */
        0.1s            /* delay */
        forwards        /* fill-mode: 끝난 상태 유지 */
        infinite;       /* iteration-count */
}

축약형. 풀어쓰면 6개 속성:

css
.el {
    animation-name: fadeIn;
    animation-duration: 0.3s;
    animation-timing-function: ease-out;
    animation-delay: 0.1s;
    animation-fill-mode: forwards;
    animation-iteration-count: infinite;
}

prefers-reduced-motion — 접근성 필수

css
@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

어지러움증 환자·전정 장애 사용자 를 위해 모션 끄기. 접근성 점수에 직결.

🤖 AI 에게 이렇게 요청해보세요

  • "이 버튼 hover 시 살짝 위로 떠오르고 그림자 진해지게 만들어줘"
  • "로딩 스피너 CSS 만들어줘. 360도 회전 0.8초 무한 반복."
  • "prefers-reduced-motion 대응 추가해줘"
먼저 읽으면 좋은 개념: 미디어 쿼리
CSS 변수 · 애니메이션 — 현대 UI 의 필수 어휘 - HTML/CSS