vibeui
히어로무료새 카드

 화면에서 오가는 로그인과 가입

왼쪽은 폼, 오른쪽은 브랜드 면이다. 로그인과 가입을 누르면 폼이 제자리에서 흐려지며 바뀌고 상자 높이가 따라 늘어난다. 라벨은 값이 들어오면 위로 떠오르고, 비밀번호는 네 가지를 세어 막대로 보여 준다.

마지막 수정

프롬프트 보고 복사하기복사해서 새 대화에 그대로 붙이면 됩니다

이 프롬프트를 실제로 실행해 나온 화면입니다

영상 원본 받기결과물 HTML 받기더블클릭하면 브라우저에서 바로 열립니다
복사해서 새 대화에 그대로

붙일 프롬프트

프롬프트 언어
붙일 도구
결과 스택
Claude Code · HTML 단일 파일
55줄 · 4,737
너는 이 저장소에서 작업하는 프론트엔드 엔지니어다. 아래 지시를 읽고 먼저 계획을 3줄로 말한 뒤 바로 파일을 만들어라. 질문은 정말 막힐 때 한 번만 해라.

# 작업: 한 화면에서 오가는 로그인과 가입

## 언제 쓰는 작업인가
로그인과 가입을 각각 다른 주소로 만들지 않고 한 화면에서 끝낼 때 쓴다. 두 폼이 같은 자리에서 바뀌기 때문에 가입하려다 로그인으로 돌아가는 사람이 화면을 다시 불러오지 않아도 된다.

## 준비물(이미 갖춰져 있다고 가정)
- 새 프로젝트다. Next.js 는 1번 뼈대가 깔려 있고, HTML 은 빈 index.html 에서 시작한다
- 서비스 이름과 오른쪽 면에 넣을 문장이 있다. 제목 한 줄, 설명 두 문장, 짧은 후기 하나
- 쓸 소셜 로그인을 정했다. 여기서는 카카오·구글·깃허브 세 개를 쓴다
- 실제 인증은 붙이지 않는다. 눌러도 서버로 보내지 않고 화면에서만 확인한다

## 건드릴 범위
인증 화면 한 장(왼쪽 폼·오른쪽 브랜드 면)까지다. 비밀번호 재설정 화면, 인증 메일 화면, 소셜 로그인 실제 연결은 만들지 않는다. 제출은 입력 검사까지만 하고 서버로 보내지 않는다.

## 결과가 이렇게 보여야 한다
화면이 좌우 반씩 나뉜다. 왼쪽은 밝은 회색 바탕에 흰 카드 한 장이 가운데 떠 있고, 카드 맨 위에는 로그인과 회원가입을 고르는 알약 두 개가 있다. 알약 뒤의 흰 배경이 옆으로 미끄러지는 동안 아래 폼이 흐려지며 바뀌고, 카드 높이도 새 폼 높이까지 늘어난다. 입력 칸에 글자를 넣으면 회색 라벨이 칸 위쪽으로 작게 올라붙는다. 비밀번호를 치면 그 아래 얇은 막대 넷이 왼쪽부터 차오르며 색이 빨강에서 초록으로 옮겨 간다. 오른쪽은 거의 검은 남색 면인데, 옅은 격자가 오른쪽 위에서만 보이다 사라지고, 그 위로 푸른 빛 한 줄이 비스듬히 아래로 천천히 흘러 내려간다.

## 구현 순서
1. 화면을 좌우로 나눈다. 바깥 요소를 display grid·grid-template-columns 1fr 1fr·min-height 100svh 로 두고, 왼쪽은 세로 가운데 정렬, 오른쪽은 position relative·overflow hidden 인 남색 면으로 둔다. 카드는 최대 폭 420px·border-radius 20px 이고, 좌우 여백은 카드가 아니라 그 안의 폼이 가진다. 카드에 좌우 여백을 주면 입력 칸의 초점 표시가 다음 단계의 overflow hidden 에 잘린다.
2. 로그인과 가입은 같은 칸에 포갠다. 두 폼을 감싼 상자를 display grid 로 두고 각 폼 상자에 grid-area 1 / 1 을 줘서 겹친다. 각 상자는 다시 display grid·grid-template-rows 0fr 이고, 켜진 쪽만 1fr 로 연다. 안쪽 폼에는 min-height 0 과 overflow hidden 이 함께 있어야 접힌다. height: auto 는 전환되지 않기 때문에 높이를 격자 행으로 만든다. 전환은 460ms cubic-bezier(.2,.75,.2,1) 이고, 폼 내용은 opacity 0·translateY(10px) 에서 제자리로 280ms 동안 오되 140ms 늦게 시작해 앞 폼이 먼저 비워지게 한다.
3. 접힌 폼은 높이가 0 이어도 키보드로는 여전히 닿는다. 꺼진 쪽 상자에 inert 를 붙여 초점이 들어가지 않게 막고, pointer-events 도 none 으로 둔다. 알약을 눌러 바꿀 때는 320ms 뒤에 새 폼의 첫 입력 칸으로 초점을 옮긴다. 바로 옮기면 아직 높이가 0 인 칸으로 들어가 화면이 덜컥 튄다.
4. 떠오르는 라벨은 :placeholder-shown 으로 잡는다. 입력 칸에 placeholder=' ' 를 반드시 넣고(빈 문자열이 아니라 빈칸 하나다) 라벨을 입력 칸 바로 뒤에 둔다. 칸은 height 56px·padding 22px 14px 8px 이고 라벨은 top 17px·left 15px 에서 시작한다. input:not(:placeholder-shown) + label 과 input:focus + label 에 transform translateY(-11px) scale(.76) 을 주면 라벨이 위쪽 빈 자리로 올라간다. 값이 없는 칸이 placeholder 를 보여 준다는 성질을 그대로 뒤집어 쓰는 방법이라, 자바스크립트가 한 줄도 필요 없다.
5. 소셜 버튼 셋은 두 폼이 같이 쓴다. 로그인과 가입 위쪽에 한 번만 두고 문구를 '카카오로 계속하기' 처럼 중립으로 적으면, 폼이 바뀌어도 고쳐 쓸 것이 없다. 아이콘은 전부 인라인 SVG 로 그리고 바깥에서 하나도 받지 않는다. 카카오는 노랑 #FEE500 바탕에 어두운 글자, 깃허브는 #17181C 바탕에 흰 글자, 구글은 흰 바탕에 경계선만 준다. 셋 아래에는 가로선 두 줄 사이에 '또는 이메일로' 를 끼운다.
6. 비밀번호 강도는 네 가지를 센다. 여덟 자 이상이면 1점, 대문자와 소문자가 함께 있으면 1점, 숫자가 있으면 1점, 글자와 숫자와 공백이 아닌 기호가 있으면 1점이다. 그 점수만큼 높이 4px·간격 5px 인 막대 넷을 왼쪽부터 채우고 색을 함께 바꾼다. 1점은 빨강 #E5484D, 2점은 주황 #F5A524, 3점은 파랑 #3D63FF, 4점은 초록 #10B981 이다. 막대는 aria-hidden 으로 감추고, 대신 그 아래 한 줄을 aria-live polite 로 두어 '아주 좋습니다' 처럼 말로 알려 준다.
7. 오류는 칸에 붙인다. 입력 칸마다 aria-describedby 로 빈 문단 하나를 묶어 두고, 문제가 있으면 그 문단을 채우면서 칸에 aria-invalid='true' 를 준다. 고쳐지면 속성을 지운다. 문단에 role='alert' 를 주면 채워지는 순간 읽어 준다. 검사는 칸에서 빠져나갈 때 한 번 하고, 이미 빨간 칸은 글자를 칠 때마다 다시 본다. 처음부터 빨갛게 만들지 않기 위해서다. 제출할 때는 전부 검사한 뒤 문제가 있는 첫 칸으로 초점을 보낸다.
8. 오른쪽 브랜드 면은 배경 세 겹이다. 첫 겹은 가로세로 1px 짜리 흰 선을 rgba(255,255,255,.055) 로 그린 46px 격자이고, mask-image radial-gradient(120% 90% at 70% 15%, #000 20%, transparent 78%) 로 오른쪽 위만 남기고 지운다. 둘째 겹은 지름 520px 짜리 푸른 원을 오른쪽 위 밖으로 걸쳐 둔 것이다. 셋째 겹은 흐르는 빛인데, 높이 46%·폭 180% 인 띠에 linear-gradient(103deg, transparent 40%, rgba(150,180,255,.20) 50%, transparent 60%) 를 칠하고 translateY 를 330% 까지 8.4초 linear 로 민다. 회전시키지 않고 그라디언트 각도만 기울이면 비스듬한 빛이 된다.
9. prefers-reduced-motion 이면 모든 animation 과 transition 을 none 으로 덮는다. 폼은 흐림 없이 즉시 바뀌고 높이도 바로 맞춰지며, 오른쪽 빛은 멈춘 채로 있는다. 980px 아래에서는 한 줄로 세워 폼을 위, 브랜드 면을 아래로 내리고 브랜드 면 높이를 340px 로 잡는다. 420px 아래에서는 카드 안쪽 여백을 18px 로 줄이고 체크박스 줄을 세로로 쌓는다. 400px 과 1440px 에서 가로 스크롤이 없는지 보고 빌드를 통과시킨다.

## 기본값(필요하면 바꿔라)
- 폼이 바뀌는 시간: 460ms (바꿀 수 있는 범위: 300ms ~ 600ms(느리면 두 번 누르게 된다))
- 폼 내용이 늦게 오는 정도: 140ms (바꿀 수 있는 범위: 0ms ~ 220ms(0 이면 두 폼이 겹쳐 보인다))
- 라벨이 올라가는 높이: -11px에 0.76배 (바꿀 수 있는 범위: -8px ~ -14px, 0.7 ~ 0.85배)
- 브랜드 면 빛이 한 번 흐르는 시간: 8.4초 (바꿀 수 있는 범위: 5초 ~ 14초)
- 격자 칸 크기: 46px (바꿀 수 있는 범위: 32px ~ 72px(작을수록 화면이 빽빽해진다))

## 하지 말 것
- 입력 칸의 placeholder 를 비워 두지 않는다. 빈칸 하나라도 없으면 :placeholder-shown 이 걸리지 않아 라벨이 영영 떠오르지 않는다.
- 폼 높이를 height: auto 로 바꾸지 않는다. 전환되지 않아 카드가 그냥 튄다.
- 접힌 폼을 그대로 두지 않는다. 높이가 0 이어도 탭 키로 들어가 보이지 않는 칸에 글자를 치게 된다.
- 오류를 칸 밖 한곳에 몰아 적지 않는다. 어느 칸이 문제인지 화면 낭독기가 알 길이 없다.
- 비밀번호 막대를 그림으로만 두지 않는다. 옆에 말로 알려 주는 한 줄이 같이 있어야 한다.
- 소셜 아이콘을 외부 주소에서 가져오지 않는다. 인증 화면이 남의 서버를 기다리다 늦게 뜬다.

## 출력 규칙 (HTML 단일 파일)
- 결과는 index.html 파일 하나로 저장한다. 외부 CDN 을 쓰지 않고 CSS·JS 를 파일 안에 넣는다.
- HTML 파일 하나로 완결한다. 별도 CSS·JS 파일을 만들지 않는다.
- 폰트는 시스템 폰트 스택을 기본으로 쓰고, 한글은 'Pretendard Variable', 'Apple SD Gothic Neo', 'Malgun Gothic' 순으로 폴백한다.
- 색·간격·둥글기는 :root 의 CSS 변수로 모아 두고, 본문에서는 변수만 참조한다.
- 1200px 데스크톱과 400px 모바일에서 가로 스크롤이 생기지 않아야 한다.
- 움직임은 prefers-reduced-motion 을 존중한다.

끝나면 만든 파일 목록과 브라우저에서 확인할 URL 을 한 줄씩 적어라.

복사한 뒤 Claude Code 새 대화에 그대로 붙이면 됩니다. 아래 값은 붙이기 전에 숫자만 바꿔도 결과가 달라집니다.

바꿔 볼 값

  • 폼이 바뀌는 시간460ms

    300ms ~ 600ms(느리면 두 번 누르게 된다)

  • 폼 내용이 늦게 오는 정도140ms

    0ms ~ 220ms(0 이면 두 폼이 겹쳐 보인다)

  • 라벨이 올라가는 높이-11px에 0.76배

    -8px ~ -14px, 0.7 ~ 0.85배

  • 브랜드 면 빛이 한 번 흐르는 시간8.4초

    5초 ~ 14초

  • 격자 칸 크기46px

    32px ~ 72px(작을수록 화면이 빽빽해진다)

붙이기 전에 한 번

언제 쓰고, 뭐가 필요한가

언제 쓰나

로그인과 가입을 각각 다른 주소로 만들지 않고 한 화면에서 끝낼 때 쓴다. 두 폼이 같은 자리에서 바뀌기 때문에 가입하려다 로그인으로 돌아가는 사람이 화면을 다시 불러오지 않아도 된다.

준비물

  • 새 프로젝트다. Next.js 는 1번 뼈대가 깔려 있고, HTML 은 빈 index.html 에서 시작한다
  • 서비스 이름과 오른쪽 면에 넣을 문장이 있다. 제목 한 줄, 설명 두 문장, 짧은 후기 하나
  • 쓸 소셜 로그인을 정했다. 여기서는 카카오·구글·깃허브 세 개를 쓴다
  • 실제 인증은 붙이지 않는다. 눌러도 서버로 보내지 않고 화면에서만 확인한다
복사해서 붙인 직후

결과는 이렇게 나옵니다

회원가입을 누르면 로그인 폼이 흐려지며 빠지고 이름 칸이 하나 늘어난 폼이 올라오면서 카드가 그만큼 길어진다. 비밀번호에 여덟 자를 치면 막대 하나가 빨갛게 차고, 대문자와 숫자와 기호를 더하면 넷이 모두 초록으로 찬다. 동의를 빼고 제출하면 체크박스 아래에 빨간 한 줄이 붙는다.

같이 쓰면 좋습니다

이어서 붙이면 좋은 카드