설명
한국 핀테크 앱이 자리 잡게 만든 모양이에요. 폼이나 온보딩에서 다음 액션을 한 손 엄지로 지연 없이 누를 수 있게 도와줍니다. 1열 폼과 함께 자연스러운 흐름을 만들고, 키보드가 올라오면 버튼이 키보드 위로 따라 올라오는 동작이 가장 중요해요. 일반 sticky bottom과는 이 부분이 달라요. 한 화면에 1차 액션 하나만 노출하기 때문에 사용자가 다음에 뭘 할지 헷갈리지 않습니다.
🖼️ 미니어처
💬 AI에게 이렇게 말하세요
- 토스 앱처럼 화면 하단에 풀와이드 단일 CTA 버튼을 고정해 주세요. 키보드가 올라오면 키보드 바로 위에 붙도록 visualViewport API로 처리합니다.
- height 56px, font 16px, border-radius 12px의 풀와이드 primary 버튼으로 만들어 주세요. 좌우 padding 16px, safe-area-inset-bottom 처리 포함.
- 폼 검증이 통과되면 활성, 안 되면 비활성(60% opacity)으로 처리합니다.
왜 토스식인가요
한국 모바일 앱은 한 손 엄지 사용 비율이 높아요. 토스는 모든 폼·온보딩에서 '한 화면 한 액션'을 강제하면서 다음 액션 버튼을 항상 같은 자리(엄지 도달 영역)에 두는 룰을 정착시켰습니다. 사용자는 다음 액션을 찾을 필요가 없고, 화면이 바뀌어도 동일한 위치에서 동일한 모양의 버튼을 눌러요.
키보드 추적 코드
useEffect(() => {
const vv = window.visualViewport
if (!vv) return
const onResize = () => {
const offset = window.innerHeight - vv.height - vv.offsetTop
document.documentElement.style.setProperty('--keyboard-offset', `${offset}px`)
}
vv.addEventListener('resize', onResize)
vv.addEventListener('scroll', onResize)
return () => {
vv.removeEventListener('resize', onResize)
vv.removeEventListener('scroll', onResize)
}
}, []) ⚡ 사용 예 (한 줄)
<div className="fixed inset-x-0 bottom-0 px-4 pb-[env(safe-area-inset-bottom)] bg-white"><Button size="lg" className="w-full h-14">다음</Button></div> 🧩 컴포넌트 매핑
shadcn/ui Button(size="lg")에 Tailwind 'fixed bottom-0 inset-x-0 px-4 pb-[env(safe-area-inset-bottom)]'를 적용합니다. 키보드 추적은 window.visualViewport의 'resize'와 'scroll' 이벤트로 처리해요.
1차 액션이 하나가 아닌데 버튼을 2~3개 한 줄에 박아 두면 풀와이드 CTA의 명확성이 사라져요.
토스가 처음 자리 잡게 했지만 카카오뱅크와 뱅크샐러드, 쏘카, 당근까지 같은 모양으로 퍼졌어요. iOS Safari에서는 visualViewport 계산이 빠지면 버튼이 키보드에 가려지고, safe-area-inset-bottom 처리를 안 하면 노치 단말 하단에서 잘립니다. 글자 크기는 14px이 아니라 16~18px이 적당해요. 한국 모바일 사용자는 글자가 작은 CTA를 진지하지 않은 버튼으로 받아들이는 경향이 있습니다.
비활성 상태를 색만으로 표현하지 마세요(aria-disabled + 안 누르는 이유 텍스트 표시). 폼 검증 실패 시 버튼을 disabled로 두기보다, 누르면 첫 에러 필드로 스크롤+포커스를 이동시키는 편이 더 친절해요.