ログイン画面 デザイン 9選 — コピペで使えるカードUI
ログイン画面 デザインはメールと入力欄・ボタンだけに見えますが、実際にはカードの質感・画面分割・ステップ進行まで9つの小さな判断でできています。9つのうち1つは、画面をぼかすと同時にモーダルを重ねて表示し、セッション切れを伝えます。
自動再生 · タイルを押すとその項目へ · すべて1つのzip
- 01 グラスモーフィズムのログインカード
- 02 スプリットスクリーンのログイン
- 03 フローティングラベルの会員登録入力欄
- 04 パスワード強度バー
- 05 ソーシャルログインボタンの並び
- 06 会員登録ステップ進行バー
- 07 マジックリンク送信完了カード
- 08 セッション切れの再ログインモーダル
- 09 利用規約同意チェックボックス
以下の9つは人気順ではなく、ログイン・会員登録画面で実際に起こる順番で並べました。カードがまず目に入り(01・02)、名前やメールを入力し(03)、パスワードを入力しながら強度を確認し(04)、ソーシャルログインのボタンを選ぶか(05)複数のステップを踏んで登録を進め(06)、メールのリンクを待ち(07)、セッションが切れて再ログインし(08)、最後に規約に同意して終わります(09)。
| 番号 | 名前 | 何が動くか | JS |
|---|---|---|---|
| 01 | グラスモーフィズムのログインカード | ブロブの transform、カードの backdrop-filter: blur |
なし |
| 02 | スプリットスクリーンのログイン | 左右パネルの translateX 進入 |
なし |
| 03 | フローティングラベルの会員登録入力欄 | ラベルの translateY + scale |
なし |
| 04 | パスワード強度バー | バーの width・背景色、ステータス文言 |
11行 |
| 05 | ソーシャルログインボタンの並び | ボタンの translateY ホバー |
なし |
| 06 | 会員登録ステップ進行バー | 連結線の width トランジション |
なし |
| 07 | マジックリンク送信完了カード | 封筒の translateY バウンス、カウントダウン |
18行 |
| 08 | セッション切れの再ログインモーダル | モーダルの scale+opacity、backdrop の blur |
なし |
| 09 | 利用規約同意チェックボックス | チェックの stroke-dashoffset 描画 |
なし |
01グラスモーフィズムのログインカード
半透明のガラス質カードが背景のグラデーションをぼかして映し、カードの奥で光の塊がゆっくり動いてガラスの質感を出します。プロダクトのランディングページのログインモーダルや、ダークテーマSaaSの最初の画面に向いています。backdrop-filter: blur はカードの奥で実際に何かが動いていないとガラスらしく見えないため、2つのブロブを transform: translate で常に動かしています。
.glass-card {
background: rgba(255, 255, 255, .14);
border: 1px solid rgba(255, 255, 255, .35);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.glass-scene__blob {
border-radius: 50%;
filter: blur(2px);
animation: drift 6s $easing infinite;
}
@keyframes drift {
0%, 100% { transform: translate(-30px, -20px) scale(1); }
50% { transform: translate(40px, 30px) scale(1.15); }
}
02スプリットスクリーンのログイン
画面を左右に分け、片側に画像やキャッチコピー、もう片側にフォームを置き、読み込み時に両方のパネルが左右から少しだけ滑り込んできます。ブランドイメージを重視するサービスのログインページや、アプリのダウンロードも一緒に訴求する認証画面に向いています。進入距離を画面幅の100%ではなく16%にとどめた理由は、下の「落とし穴」の段落にあります。
.split { display: flex; overflow: hidden; }
.split__panel--image { animation: enter-left 2s $easing infinite; }
.split__panel--form { animation: enter-right 2s $easing infinite; }
@keyframes enter-left {
0%, 100% { transform: translateX(-16%); }
35%, 90% { transform: translateX(0); }
}
03フローティングラベルの会員登録入力欄
入力欄の中にあったラベルが、フォーカスされるか値が入ると上に浮き上がって小さくなり、placeholder が消えても何の欄か分かり続けます。メール・氏名・電話番号を集める会員登録フォームや、縦のスペースを節約したいモバイルフォームに使います。鍵は input:not(:placeholder-shown) で、placeholder=" "(スペース1つ)を入れておくと値が空のときだけこの状態になるので、JS なしでラベルが浮き上がります。
.float-field__label {
transform-origin: left center;
transition: transform $duration $easing, color $duration $easing;
}
.float-field__input:focus + .float-field__label,
.float-field__input:not(:placeholder-shown) + .float-field__label {
transform: translateY(-135%) scale(.78);
color: $color;
}
04パスワード強度バー
入力中のパスワードの長さと文字の組み合わせに応じてバーが赤→オレンジ→緑に伸びていき、横のテキストが「弱い・普通・強い」をリアルタイムで知らせます。会員登録のパスワード入力欄やパスワード変更画面向けです。長さ・大文字小文字の混在・数字・記号の4つをそれぞれ test() で確認してスコアを出し、そのスコアでバーの幅と色を一度に変えます。
.pw-meter__fill { transition: width $duration $easing, background-color $duration $easing; }
inp.addEventListener('input', function(){
var v = inp.value, s = 0;
if (v.length >= 6) s++;
if (/[a-z]/.test(v) && /[A-Z]/.test(v)) s++;
if (/[0-9]/.test(v)) s++;
if (/[^A-Za-z0-9]/.test(v)) s++;
var pct = v.length ? [15,40,70,100,100][s] : 0;
fill.style.width = pct + '%';
});
05ソーシャルログインボタンの並び
Google・Apple・Kakao のようなソーシャルログインボタンが一列に並び、カーソルを乗せた瞬間だけわずかに浮き上がって影が濃くなります。メール登録より前に置くソーシャルログイン優先画面や、複数のログイン手段を並べて見せたいサービスに使います。動くのは transform: translateY だけで top は使わないため、レイアウトが再計算されません。
.social-btn {
transition: transform $duration $easing, box-shadow $duration $easing;
}
.social-btn:hover, .social-btn:focus-visible {
transform: translateY(-3px);
box-shadow: $shadow-press;
}
06会員登録ステップ進行バー
1・2・3のステップの点が線でつながっていて、次のステップに進むたびにその線が伸びるアニメーションが再生されます。情報を分けて受け取る複数ステップの会員登録や、決済前に複数ステップを踏むオンボーディングに使います。React 版では step という props ひとつで、その手前の連結線の width が切り替わるようにしているので、親は今どのステップかを渡すだけで済みます。
.stepper__fill {
width: 0%;
background: $color;
border-radius: $r-xs;
}
.stepper.is-demo .stepper__fill--1 { animation: fill-1 $dur-loop $easing infinite; }
.stepper.is-demo .stepper__step--1 .stepper__dot,
.stepper.is-demo .stepper__step--2 .stepper__dot {
animation: dot-fill $dur-loop step-end infinite;
}
07マジックリンク送信完了カード
パスワードなしでリンクからログインする方式で、メール送信直後に封筒アイコンが跳ね、再送信ボタンはカウントダウンが終わるまで押せません。パスワードレス(マジックリンク)ログインを使うサービスや、メール認証待ちの画面に向いています。封筒のバウンスは常に回っている CSS の @keyframes ですが、カウントダウンは1秒ごとに数字を減らし0になるとボタンを解除する、18行の実際の setInterval です。
var n = 30;
var timer = setInterval(function () {
n--;
cnt.textContent = n;
if (n <= 0) {
clearInterval(timer);
btn.disabled = false;
btn.textContent = 'Resend link';
}
}, 1000);
08セッション切れの再ログインモーダル
一定時間が過ぎてセッションが切れると背景がぼやけ、モーダルが拡大しながら現れて、もう一度ログインしないと元の画面に戻れないことを伝えます。管理画面の自動ログアウト通知や、しばらく放置してから開き直すウェブアプリに使います。
.modal-scene__backdrop {
background: rgba(23, 20, 26, 0);
backdrop-filter: blur(0px);
transition: background $duration $easing, backdrop-filter $duration $easing;
}
.modal-scene__modal {
transform: translate(-50%, -50%) scale(.7);
opacity: 0;
transition: transform $duration $easing, opacity $duration $easing;
}
09利用規約同意チェックボックス
四角い枠をタップするとチェックマークが線を描くように現れ、隣の「規約に同意します」という文言と一緒にカードの枠線の色が変わります。会員登録の最後のステップで行う利用規約・プライバシー同意や、マーケティング受信同意のチェックに使います。実際の <input type="checkbox"> を画面上でだけ隠し、SVG の path に pathLength="1" を指定して stroke-dashoffset を0〜1の一つの値で扱うため、スクリーンリーダーは隠れた本物のチェックボックスをそのまま読み上げます。
.consent__check {
stroke-dasharray: 1;
stroke-dashoffset: 1;
transition: stroke-dashoffset $duration $easing;
}
.consent__input:checked ~ .consent__box .consent__check {
stroke-dashoffset: 0;
}
.consent-card:has(.consent__input:checked) {
border-color: $color;
}
どこで壊れるか(落とし穴)
02番のスプリットスクリーンは最初、進入距離を画面幅の100%(画面の外まで完全に)にしていたところ、自動再生プレビューの静止画(ポスター)がよりによってパネルが半分だけ入った瞬間を捉えてしまい、「文字が切れたカード」に見えました。ポスターはフレーム間でピクセルが最も大きく変わった瞬間を選ぶのですが、スライド進入アニメーションではその「最も大きく変わる瞬間」が必ずパネルが半分かかった状態になってしまうのが原因です。進入距離を16%に縮めたところ、どのフレームを捉えても文字とボタンがきちんと見えるようになりました。カードやボタンの登場アニメーションで「画面外からの登場」を必ず100%移動にする必要はないと分かりました。08番のセッション切れモーダルも同じ理由で、トランジション区間を1周期の15%以内に短く収めています。この9つのファイルの圧縮パスワードはfc9jedg2で、箱や色で強調せずこの文章の中にそのまま書いています。
アクセシビリティ
9つとも prefers-reduced-motion: reduce ではループとトランジションを止め、最終状態に近いところで落ち着きます。01はブロブが止まりガラスの見た目だけ残り、02は両パネルが中央で止まり、03はラベルの切り替えが瞬時に起こり、04はバーがトランジションなしでそのまま値に切り替わり、06はループが止まって連結線が初期状態のまま残り、05はホバーの浮き上がりが即座に効き、07は封筒のバウンスが止まりカウントダウンの数字だけ残り、08はモーダルがトランジションなしで表示・非表示になり、09はチェックの線がトランジションなしで即座に描かれます。03・09番のように実際のフォーム要素(input)をそのまま使っている項目は、キーボードのタブ移動とスクリーンリーダーが標準のまま動きます。09番の role はブラウザ標準のチェックボックスの役割をそのまま使い、独自には指定していません。backdrop-filter のブラウザ対応状況は MDN のドキュメントで確認できます。チェックボックス・ラジオ系のアニメーションをもっと見たい方は、チェックボックス・ラジオのカスタムアニメーション集と、フォーカス状態を扱う入力欄フォーカス効果集も合わせてどうぞ。
FAQ
03番のフローティングラベルは本当にJSが一切要りませんか?
はい。placeholder=" "(スペース1つ)を入れておくと :placeholder-shown は欄が空のときだけ真になるので、input:not(:placeholder-shown) + label と input:focus + label という2つのセレクタだけでラベルが上下します。React 版でも useState を使わず同じ CSS をそのまま使っています。
09番のチェックボックスは実際にフォーム送信に使えますか?
はい。画面上は opacity: 0 で隠しているだけで、実際の <input type="checkbox"> はそのまま存在するので、<form> の中に name 属性付きで置けば他のチェックボックスと同じように値が送信されます。見た目のチェックアイコンは、その本物のチェックボックスの状態をなぞる装飾にすぎません。
07番のカウントダウンはタブがバックグラウンドにあるとどうなりますか?
多くのブラウザはバックグラウンドタブで setInterval の間隔を遅らせる(スロットリングする)ため、カウントダウンが本来の30秒より遅く進むことがあります。正確な時間が重要な場合は、開始時刻を保存しておき Date.now() との差分から残り秒数を計算し直す方が安全です。