버튼 상태

다섯 가지 상태. 첫 행은 각 상태를 강제로 고정해놓은 비교용. 두 번째 행은 실제로 만져보는 버튼.

상태별 비교 (고정)
default
hover
active (pressed)
disabled
loading
실제로 만져보기
/* 핵심 패턴 */
.btn:hover { background: var(--primary-dark); }
.btn:active { transform: scale(0.97); }
.btn[disabled] { background: #94a3b8; cursor: not-allowed; opacity: 0.7; }
.btn.is-loading { /* 스피너 + cursor: progress + 클릭 비활성 */ }

위계 (hierarchy)

한 화면에 여러 버튼이 있을 때 "뭐가 가장 중요한가" 를 시각적으로 알려준다.

.btn          /* primary: 꽉 찬 색, 메인 액션 */
.btn-secondary /* 테두리만, 보조 액션 */
.btn-ghost     /* 배경 없음, 가장 낮은 위계 */
.btn-danger    /* 빨강, 위험한 동작 (삭제 등) */

입력창 상태 (input)

클릭해서 focus 해보세요. 에러 입력창은 빨간 테두리 + 메시지.

이메일 형식을 확인해주세요.
.input:focus { border-color: var(--primary);
              box-shadow: 0 0 0 3px rgba(37,99,235,.15); }
.input.is-error { border-color: var(--danger); }

카드 상태 (card)

호버하면 살짝 떠오름. 클릭해서 선택 가능.

플랜 A

가벼운 시작

플랜 B

표준 추천

플랜 C

풀 옵션

.card:hover { transform: translateY(-3px); box-shadow: ...; }
.card.is-selected { border-color: var(--primary); }

토스트 (toast)

3초 뒤 자동으로 사라진다.

setTimeout(() => toast.remove(), 3000);
/* "3초 뒤 자동으로 사라져라" 처럼 시간을 같이 준다 */

툴팁 (tooltip)

호버하면 작은 설명이 위에 뜬다.

이건 툴팁입니다.
.tooltip { opacity: 0; transition: opacity 0.15s; }
.tooltip-wrap:hover .tooltip { opacity: 1; }

애니메이션 property

무엇이 움직이는가. 버튼을 눌러 토글하면서 비교.

opacity (투명도)
transform: translateX (위치)
scale (크기)
opacity + translateY (콤보)
/* 흔히 보는 "아래에서 떠오르며 나타나는" 효과 = opacity + translateY 콤보 */
.combo { transform: translateY(20px); opacity: 0;
         transition: transform 0.4s ease-out, opacity 0.4s ease-out; }
.combo.is-shown { transform: translateY(0); opacity: 1; }

duration 비교

같은 거리를 다른 시간으로. 즉각적 / 자연스러움 / 느긋의 차이.

0.15초 — 즉각적 (버튼 반응)
0.3초 — 자연스러움 (화면 전환 기본)
0.8초 — 느긋, 우아 (의도적)
.d150 { transition: left 0.15s ease-out; }  /* 즉각적 */
.d300 { transition: left 0.3s  ease-out; }  /* 자연스러움 */
.d800 { transition: left 0.8s  ease-out; }  /* 느긋 */

easing 비교

같은 거리, 같은 시간, 다른 가속. 곡선의 차이가 인상을 결정한다.

linear
ease-in
ease-out
ease-in-out
bounce
.linear      { transition: left 1s linear; }
.ease-in     { transition: left 1s ease-in;     /* 천천히 출발 */ }
.ease-out    { transition: left 1s ease-out;    /* 천천히 도착 — 등장에 자연스러움 */ }
.ease-in-out { transition: left 1s ease-in-out; }
.bounce      { transition: left 1s cubic-bezier(.34, 1.56, .64, 1); /* 끝에서 튕김 */ }