좋은 버튼은 화려한 버튼이 아니라 ‘누를 수 있다’와 ‘지금 처리 중이다’를 분명히 말하는 버튼입니다. Findable은 transform·opacity 기반의 가벼운 효과로 그 신호를 강화하고, 포커스·터치 크기·로딩 상태 같은 기본을 절대 빼먹지 않습니다.
요약
- 효과는 ‘누를 수 있다’는 신호를 강화할 때만 의미가 있다 — 장식이 목적이 아니다.
- 아래 8가지 버튼은 모두 transform·opacity 기반이라 60fps로 가볍게 돈다.
- 로딩 상태·포커스 링·44px 터치 타깃은 멋보다 먼저다.
- 버튼 글자는 ‘확인’이 아니라 ‘무료 진단 받기’처럼 결과를 동사로.
입사 첫 해에 선배가 제 PR을 보고 한마디 했습니다. “버튼은 잘 만들었는데, 누가 눌렀는지 버튼은 알고 있냐?” 무슨 말인가 했죠. 사용자가 제출을 눌렀는데 아무 반응이 없으면, 사람은 한 번 더 누릅니다. 그렇게 문의가 두 번 들어오고, 결제가 두 번 됩니다. 그날 이후로 저는 버튼을 ‘모양’이 아니라 ‘상태를 가진 작은 기계’로 봅니다.
그래서, 직접 눌러보세요
설명보다 빠릅니다. 아래 버튼에 마우스를 올리고, 눌러보세요. 각각 왜 이렇게 만들었는지는 바로 아래에 적었습니다.
전부 진짜로 동작합니다
호버 / 클릭 / 키보드 Tab 모두 시도해 보세요.
// 마지막 버튼은 커서를 따라오고, 클릭하면 물결이 퍼집니다.
제 진짜 무기는 화려한 게 아니라 이겁니다
위 버튼들은 사실 ‘쇼’입니다. 일을 하면서 가장 자주 다듬는 건 따로 있습니다. 바로 제출 버튼의 상태. 사용자가 누른 다음 1초가 신뢰를 만듭니다. 아래 버튼을 눌러보세요.
눌러보세요 — 누른 뒤가 진짜입니다
클릭 → 로딩(스피너) → 완료(체크) → 원복. 이 짧은 피드백이 “두 번 누르기”를 막습니다.
// 처리 중에는 버튼이 비활성화돼서 중복 제출이 안 됩니다.
화려한 효과 10개보다, 이 로딩 상태 하나가 실제 매출을 더 지킵니다. 결제·문의·예약처럼 ‘되돌릴 수 없는 행동’ 앞에서는 무조건 이걸 넣습니다.
버튼에 대해, 나만 아는 실무 이야기
1. 포커스 링을 지우는 순간 누군가는 길을 잃습니다
outline:none은 디자이너를 기쁘게 하고 키보드 사용자를 버립니다. 마우스 없이 Tab으로만 사이트를 쓰는 사람에게 포커스 링은 ‘내가 지금 여기 있다’는 유일한 표시입니다. 보기 싫으면 지우지 말고 :focus-visible로 브랜드 색에 맞춰 다시 그립니다. 위 버튼들도 Tab으로 이동해 보면 링이 살아 있습니다.
2. 눈에 보이는 크기보다 ‘누를 수 있는 크기’가 중요합니다
디자인상 버튼이 작아 보여도, 실제 터치 영역은 최소 44×44px를 확보합니다. 패딩이나 투명한 히트 영역으로요. 모바일에서 ‘분명히 눌렀는데 안 눌리는’ 경험의 절반은 여기서 옵니다.
3. 60fps의 비밀은 ‘무엇을 바꾸지 않느냐’입니다
저는 호버에 width나 top을 거의 안 건드립니다. 그건 브라우저가 레이아웃을 다시 계산하게 만들어 끊깁니다. 대신 transform(이동·확대·회전)과 opacity만 씁니다. 이 둘은 GPU가 처리해서 부드럽습니다. 이 페이지 버튼이 많은데도 가벼운 이유입니다.
제가 어떤 버튼이든 출발점으로 까는 ‘기본 골격’은 이렇습니다. 화려한 효과보다 이 네 줄(transform 호버·focus-visible·44px·reduced-motion)이 먼저입니다.
.btn{
min-height: 44px; /* 터치 타깃 최소 44×44px */
transition: transform .18s ease-out; /* layout 말고 transform만 */
}
.btn:hover{ transform: translateY(-2px); } /* GPU 처리 → 60fps */
.btn:active{ transform: translateY(0) scale(.98); } /* 눌린 손맛 */
.btn:focus-visible{ /* 키보드 사용자 길잡이 — 지우지 말 것 */
outline: 2px solid currentColor;
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce){
.btn{ transition: none; }
}위 8가지 효과 버튼도 전부 이 골격 위에 얹혀 있습니다. :focus-visible로 포커스 링을 살리고, transform만 움직여 끊김을 막는 게 시작이자 끝입니다.
4. 모션은 ‘의미’가 있을 때만
모든 게 통통 튀면 아무것도 강조되지 않습니다. 저는 화면에서 가장 중요한 버튼 하나에만 살짝 더 신경을 줍니다(예: 위의 마그네틱 버튼처럼). 그리고 prefers-reduced-motion을 켠 사용자에게는 애니메이션을 꺼서 멀미를 만들지 않습니다. 멋과 배려는 같이 갑니다.
| 항목 | 밋밋한 버튼 | 설계된 버튼 |
|---|---|---|
| 누른 뒤 피드백 | 없음 → 중복 클릭 | 로딩·완료 상태로 안심 |
| 키보드 접근 | 포커스 링 제거 | :focus-visible로 유지 |
| 성능 | width·shadow 변경 → 끊김 | transform·opacity → 60fps |
| 글자 | “확인” | “무료 진단 받기” |
버튼 하나를 이렇게 보는 사람이, 사이트 전체를 만듭니다
버튼은 사이트에서 사용자가 ‘행동’하는 거의 유일한 지점입니다. 그 0.2초를 진지하게 다루는 사람이라면, 폼도 카피도 속도도 같은 태도로 다룹니다. Findable에서는 이런 디테일이 기본값입니다. 당신의 사이트, 어떤 버튼을 만들어 드릴까요?
버튼에 애니메이션을 넣으면 전환이 오르나요?
특수 효과 버튼은 성능에 나쁘지 않나요?
포커스 링(파란 테두리)은 지워도 되나요?
버튼 글자는 어떻게 써야 하나요?
모바일에서 버튼 크기는 얼마가 적당한가요?
모션 담당자의 스크롤 애니메이션 모드
실제로 동작하는 애니메이션 모드들.
개발은 이렇게 합니다
웹표준·성능·구조화 데이터 내장.
역량 — 라이브 데모
인터랙션 8종을 한 페이지에서.
이 글의 모든 버튼은 이 페이지에서 실제로 동작하는 코드입니다(전부 transform·opacity 기반, 외부 라이브러리 0). 전환·클릭률 수치는 일반 원칙이며 특정 성과를 보장하지 않습니다. 날조된 사례·수치는 사용하지 않았습니다.