浮动标签输入框
标签在空输入框里像占位文字一样,聚焦或输入后会浮到边框上。
只用 CSS 为 React 文本输入框制作浮动标签。把 <input> 和它的 <label> 放在一个相对定位的容器中;给输入框设置 placeholder=" "(一个空格),这样就能用 :placeholder-shown 判断是否为空。为空且未聚焦时,标签以正常大小垂直居中在输入框内。在 :focus 或非 :placeholder-shown 时,用 transform: translateY(-145%) scale(0.8) 把标签上移,transform-origin 为左侧,时长 200ms,缓动为 cubic-bezier(0.16, 1, 0.3, 1),并给标签加上与输入框相同的背景色,让它切断边框。聚焦时边框和标签变为强调色。标签保持为真正的 <label for>。在 prefers-reduced-motion 下标签直接移动,不做过渡。标签文字为“邮箱地址”。
源代码
'use client'
import { useId } from 'react'
import s from './demo.module.css'
export default function FloatingLabel({ labels }: { labels: Record<string, string> }) {
const id = useId()
return (
<div className={s.field}>
<input id={id} className={s.input} type="email" placeholder=" " autoComplete="off" />
<label htmlFor={id} className={s.label}>
{labels.label}
</label>
</div>
)
}
.field { position: relative; width: min(280px, 100%); }
.input {
width: 100%;
height: 54px;
padding: 0 16px;
border: 1px solid var(--stage-rule);
border-radius: 12px;
outline: none;
background: var(--stage-bg);
color: var(--stage-ink);
font: 400 var(--text-base) / 1 var(--font-body);
transition: border-color 200ms var(--ease-out);
}
.input:hover { border-color: var(--stage-muted); }
.input:focus { border-color: var(--stage-accent); }
.input:focus-visible { box-shadow: 0 0 0 3px var(--color-focus); }
.label {
position: absolute;
top: 50%;
left: 12px;
padding: 0 4px;
background: var(--stage-bg);
color: var(--stage-muted);
font: 400 var(--text-base) / 1 var(--font-body);
transform: translateY(-50%);
transform-origin: left;
pointer-events: none;
transition: transform 200ms var(--ease-out), color 200ms var(--ease-out);
}
.input:focus + .label,
.input:not(:placeholder-shown) + .label {
transform: translateY(-145%) scale(0.8);
}
.input:focus + .label { color: var(--stage-accent); }
@media (prefers-reduced-motion: reduce) {
.label, .input { transition: none; }
}