フローティングラベル
入力時にラベルが上へ縮小移動する定番のフォームUI。:placeholder-shown とトランジションだけで実現し、ログインや登録画面に使えます。
ライブデモ
使用例(お題: カフェ MOON BREW)
この技法を「カフェ MOON BREW」というテーマのダミーサイトで実際に使った例です。
HTML
<div class="mb-screen">
<!-- 左:店舗ビジュアル -->
<aside class="mb-hero">
<span class="mb-logo">☕ MOON BREW</span>
<h1 class="mb-hero__title">月夜の<br>ご予約</h1>
<p class="mb-hero__lead">焙煎したての一杯を、<br>静かな夜の席で。</p>
<p class="mb-hero__hours">営業 11:00 – 23:00 / 不定休</p>
</aside>
<!-- 右:フローティングラベルの予約フォーム -->
<form class="mb-form" novalidate>
<h2 class="mb-form__title">来店予約</h2>
<div class="field">
<input id="mb-name" class="field__input" type="text" placeholder=" " autocomplete="off">
<label class="field__label" for="mb-name">お名前</label>
<span class="field__line"></span>
</div>
<div class="field">
<input id="mb-tel" class="field__input" type="tel" placeholder=" " autocomplete="off">
<label class="field__label" for="mb-tel">電話番号</label>
<span class="field__line"></span>
</div>
<div class="field field--row">
<div class="field">
<input id="mb-date" class="field__input" type="text" placeholder=" " value="6/14(土)">
<label class="field__label" for="mb-date">来店日</label>
<span class="field__line"></span>
</div>
<div class="field">
<input id="mb-num" class="field__input" type="text" placeholder=" " value="2名">
<label class="field__label" for="mb-num">人数</label>
<span class="field__line"></span>
</div>
</div>
<button class="mb-btn" type="submit">この内容で予約する</button>
</form>
</div>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
background: #2b1d12;
color: #2b1d12;
}
/* 2カラムのカフェ予約画面 */
.mb-screen {
width: min(680px, 94vw);
height: 372px;
display: grid;
grid-template-columns: 1fr 1.1fr;
background: #f5ede1;
border-radius: 18px;
overflow: hidden;
box-shadow: 0 26px 60px -22px rgba(0, 0, 0, 0.6);
}
/* 左ヒーロー:コーヒー写真風グラデ */
.mb-hero {
position: relative;
padding: 26px 24px;
color: #f5ede1;
background:
linear-gradient(160deg, rgba(43, 29, 18, 0.86), rgba(43, 29, 18, 0.55)),
radial-gradient(120% 90% at 80% 10%, #c98a3b 0%, #2b1d12 70%);
}
.mb-logo { font-size: 0.82rem; font-weight: 700; letter-spacing: 0.08em; }
.mb-hero__title { margin: 36px 0 14px; font-size: 1.9rem; line-height: 1.25; font-weight: 800; }
.mb-hero__lead { margin: 0; font-size: 0.86rem; line-height: 1.7; opacity: 0.92; }
.mb-hero__hours {
position: absolute; left: 24px; bottom: 22px;
margin: 0; font-size: 0.74rem; letter-spacing: 0.04em;
color: #e7c79a;
}
/* 右フォーム */
.mb-form { padding: 28px 28px 24px; display: flex; flex-direction: column; }
.mb-form__title {
margin: 0 0 20px; font-size: 1.05rem; font-weight: 700;
letter-spacing: 0.04em; color: #2b1d12;
}
.field { position: relative; margin-bottom: 20px; flex: 1; }
.field--row { display: flex; gap: 16px; margin-bottom: 20px; }
.field--row .field { margin-bottom: 0; }
.field__input {
width: 100%;
padding: 16px 2px 7px;
font-size: 0.95rem;
color: #2b1d12;
background: transparent;
border: none;
border-bottom: 2px solid #d8c4a6;
outline: none;
}
.field__label {
position: absolute;
left: 2px;
top: 14px;
font-size: 0.95rem;
color: #a98c63;
pointer-events: none;
transform-origin: left top;
transition: transform 0.22s ease, color 0.22s ease;
}
/* フォーカス/入力時にラベルを上へ縮小移動(技法の主役) */
.field__input:focus + .field__label,
.field__input:not(:placeholder-shown) + .field__label {
transform: translateY(-15px) scale(0.78);
color: #c98a3b;
}
.field__line {
position: absolute;
left: 0; bottom: 0;
height: 2px; width: 100%;
background: linear-gradient(90deg, #c98a3b, #e7b873);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.28s ease;
}
.field__input:focus ~ .field__line { transform: scaleX(1); }
.mb-btn {
margin-top: 6px;
padding: 13px;
font-size: 0.95rem;
font-weight: 700;
letter-spacing: 0.05em;
color: #f5ede1;
background: linear-gradient(135deg, #c98a3b, #a96e26);
border: none;
border-radius: 11px;
cursor: pointer;
box-shadow: 0 12px 22px -10px rgba(169, 110, 38, 0.8);
transition: transform 0.15s ease;
}
.mb-btn:hover { transform: translateY(-2px); }
.mb-btn:active { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
.field__label, .field__line, .mb-btn { transition: none; }
}
JavaScript
// 予約フォームの送信デモ:実送信せずボタンで完了表示
const form = document.querySelector(".mb-form");
if (form) {
form.addEventListener("submit", (e) => {
e.preventDefault();
const btn = form.querySelector(".mb-btn");
if (!btn) return;
const label = btn.textContent;
btn.textContent = "ご予約を承りました ✓";
btn.style.background = "linear-gradient(135deg,#3f7d4f,#5aa06a)";
// 1.8秒後に元へ戻す
setTimeout(() => {
btn.textContent = label;
btn.style.background = "";
}, 1800);
});
}
コード
HTML
<div class="stage">
<form class="float-form" novalidate>
<h2 class="float-title">アカウント作成</h2>
<!-- 入力欄+ラベルのペア。:placeholder-shown でラベルが浮く -->
<div class="field">
<input id="fl-name" class="field__input" type="text" placeholder=" " autocomplete="off">
<label class="field__label" for="fl-name">お名前</label>
<span class="field__line"></span>
</div>
<div class="field">
<input id="fl-mail" class="field__input" type="email" placeholder=" " autocomplete="off">
<label class="field__label" for="fl-mail">メールアドレス</label>
<span class="field__line"></span>
</div>
<div class="field">
<input id="fl-pass" class="field__input" type="password" placeholder=" " autocomplete="off">
<label class="field__label" for="fl-pass">パスワード</label>
<span class="field__line"></span>
</div>
<button class="float-btn" type="submit">登録する</button>
</form>
</div>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
/* 斜めグラデの落ち着いた背景 */
background: linear-gradient(135deg, #1e2a44 0%, #25406b 55%, #3a6ea5 100%);
color: #1f2937;
}
.stage { width: 100%; padding: 24px; display: grid; place-items: center; }
.float-form {
width: min(340px, 90vw);
padding: 32px 28px 28px;
background: rgba(255, 255, 255, 0.96);
border-radius: 18px;
box-shadow: 0 24px 60px -20px rgba(8, 18, 40, 0.55);
}
.float-title {
margin: 0 0 22px;
font-size: 1.15rem;
font-weight: 700;
letter-spacing: 0.04em;
color: #1e293b;
}
/* 入力欄まわり */
.field { position: relative; margin-bottom: 22px; }
.field__input {
width: 100%;
padding: 18px 2px 8px;
font-size: 1rem;
color: #111827;
background: transparent;
border: none;
border-bottom: 2px solid #cbd5e1;
outline: none;
}
/* ラベルの初期位置=入力欄の中 */
.field__label {
position: absolute;
left: 2px;
top: 16px;
font-size: 1rem;
color: #94a3b8;
pointer-events: none;
transform-origin: left top;
transition: transform 0.22s ease, color 0.22s ease;
}
/* フォーカス時/入力済み時にラベルを上へ縮小移動 */
.field__input:focus + .field__label,
.field__input:not(:placeholder-shown) + .field__label {
transform: translateY(-16px) scale(0.78);
color: #2563eb;
}
/* 下線をフォーカスで左から伸ばす演出 */
.field__line {
position: absolute;
left: 0;
bottom: 0;
height: 2px;
width: 100%;
background: linear-gradient(90deg, #2563eb, #38bdf8);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.28s ease;
}
.field__input:focus ~ .field__line { transform: scaleX(1); }
.float-btn {
width: 100%;
margin-top: 4px;
padding: 13px;
font-size: 1rem;
font-weight: 700;
letter-spacing: 0.05em;
color: #fff;
background: linear-gradient(135deg, #2563eb, #4f46e5);
border: none;
border-radius: 12px;
cursor: pointer;
box-shadow: 0 12px 24px -10px rgba(37, 99, 235, 0.7);
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.float-btn:hover { transform: translateY(-2px); box-shadow: 0 18px 30px -10px rgba(37, 99, 235, 0.8); }
.float-btn:active { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
.field__label, .field__line, .float-btn { transition: none; }
}
JavaScript
// 送信デモ:ページ遷移を止めて簡単なフィードバックを返す
const form = document.querySelector(".float-form");
if (form) {
form.addEventListener("submit", (e) => {
e.preventDefault();
const btn = form.querySelector(".float-btn");
if (!btn) return;
const label = btn.textContent;
btn.textContent = "登録しました ✓";
btn.style.background = "linear-gradient(135deg,#16a34a,#22c55e)";
// 1.6秒後に元へ戻す
setTimeout(() => {
btn.textContent = label;
btn.style.background = "";
}, 1600);
});
}
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「フローティングラベル」の効果を追加してください。
# 追加してほしい効果
フローティングラベル(フォーム & 入力)
入力時にラベルが上へ縮小移動する定番のフォームUI。:placeholder-shown とトランジションだけで実現し、ログインや登録画面に使えます。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<div class="stage">
<form class="float-form" novalidate>
<h2 class="float-title">アカウント作成</h2>
<!-- 入力欄+ラベルのペア。:placeholder-shown でラベルが浮く -->
<div class="field">
<input id="fl-name" class="field__input" type="text" placeholder=" " autocomplete="off">
<label class="field__label" for="fl-name">お名前</label>
<span class="field__line"></span>
</div>
<div class="field">
<input id="fl-mail" class="field__input" type="email" placeholder=" " autocomplete="off">
<label class="field__label" for="fl-mail">メールアドレス</label>
<span class="field__line"></span>
</div>
<div class="field">
<input id="fl-pass" class="field__input" type="password" placeholder=" " autocomplete="off">
<label class="field__label" for="fl-pass">パスワード</label>
<span class="field__line"></span>
</div>
<button class="float-btn" type="submit">登録する</button>
</form>
</div>
【CSS】
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
/* 斜めグラデの落ち着いた背景 */
background: linear-gradient(135deg, #1e2a44 0%, #25406b 55%, #3a6ea5 100%);
color: #1f2937;
}
.stage { width: 100%; padding: 24px; display: grid; place-items: center; }
.float-form {
width: min(340px, 90vw);
padding: 32px 28px 28px;
background: rgba(255, 255, 255, 0.96);
border-radius: 18px;
box-shadow: 0 24px 60px -20px rgba(8, 18, 40, 0.55);
}
.float-title {
margin: 0 0 22px;
font-size: 1.15rem;
font-weight: 700;
letter-spacing: 0.04em;
color: #1e293b;
}
/* 入力欄まわり */
.field { position: relative; margin-bottom: 22px; }
.field__input {
width: 100%;
padding: 18px 2px 8px;
font-size: 1rem;
color: #111827;
background: transparent;
border: none;
border-bottom: 2px solid #cbd5e1;
outline: none;
}
/* ラベルの初期位置=入力欄の中 */
.field__label {
position: absolute;
left: 2px;
top: 16px;
font-size: 1rem;
color: #94a3b8;
pointer-events: none;
transform-origin: left top;
transition: transform 0.22s ease, color 0.22s ease;
}
/* フォーカス時/入力済み時にラベルを上へ縮小移動 */
.field__input:focus + .field__label,
.field__input:not(:placeholder-shown) + .field__label {
transform: translateY(-16px) scale(0.78);
color: #2563eb;
}
/* 下線をフォーカスで左から伸ばす演出 */
.field__line {
position: absolute;
left: 0;
bottom: 0;
height: 2px;
width: 100%;
background: linear-gradient(90deg, #2563eb, #38bdf8);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.28s ease;
}
.field__input:focus ~ .field__line { transform: scaleX(1); }
.float-btn {
width: 100%;
margin-top: 4px;
padding: 13px;
font-size: 1rem;
font-weight: 700;
letter-spacing: 0.05em;
color: #fff;
background: linear-gradient(135deg, #2563eb, #4f46e5);
border: none;
border-radius: 12px;
cursor: pointer;
box-shadow: 0 12px 24px -10px rgba(37, 99, 235, 0.7);
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.float-btn:hover { transform: translateY(-2px); box-shadow: 0 18px 30px -10px rgba(37, 99, 235, 0.8); }
.float-btn:active { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
.field__label, .field__line, .float-btn { transition: none; }
}
【JavaScript】
// 送信デモ:ページ遷移を止めて簡単なフィードバックを返す
const form = document.querySelector(".float-form");
if (form) {
form.addEventListener("submit", (e) => {
e.preventDefault();
const btn = form.querySelector(".float-btn");
if (!btn) return;
const label = btn.textContent;
btn.textContent = "登録しました ✓";
btn.style.background = "linear-gradient(135deg,#16a34a,#22c55e)";
// 1.6秒後に元へ戻す
setTimeout(() => {
btn.textContent = label;
btn.style.background = "";
}, 1600);
});
}
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。