:focus仅检测焦点状态而非输入内容,正确方案是用:placeholder-shown判断是否已输入;需确保placeholder=" "、label紧邻input、for/id匹配,并手动触发input事件更新状态。

为什么只用 :focus 会失败
很多初学者写 input:focus + label 就以为完事了,结果用户输完内容一点击别处,label 立刻掉回框里盖住文字。这不是 bug,是逻辑缺陷:聚焦状态(:focus)只管“当前有没有焦点”,不管“里面有没有值”。只要失焦,样式就退回,和输入内容重叠。
真正要捕获的是「已输入」这个语义状态,而浏览器原生支持的判断依据只有一个::placeholder-shown —— 它只在 placeholder 正显示时匹配;一旦有任意可见字符(哪怕一个空格),它就失效,:not(:placeholder-shown) 就成立。
-
:placeholder-shown不是装饰性伪类,它是状态信号,类似布尔开关 - 没有
placeholder属性,:placeholder-shown永远不触发,整个浮动逻辑瘫痪 -
placeholder=""(空字符串)等同于没写,必须写成placeholder=" "(一个空格)才有效
label 必须紧跟 input 且用 + 选择器
CSS 浮动依赖相邻兄弟选择器(input + label),这意味着 HTML 结构必须严格满足:label 元素必须直接跟在 input 后面,中间不能有换行、注释或任何其他节点干扰。
错误写法(失效):<input placeholder=" "><div></div>
<label for="x">姓名</label>
正确写法(生效):<input type="text" id="name" placeholder=" "><label for="name">姓名</label>
-
for和id必须严格对应,否则可访问性断裂,屏幕阅读器无法关联 - 不要把
label包在input外层,嵌套结构会让+选择器完全不匹配 - 如果用
textarea,同样适用;但select不触发:placeholder-shown,需另配 JS fallback
三种状态必须分别覆盖,不能只靠 :not(:placeholder-shown)
一个健壮的浮动标签要响应三类场景:空且未聚焦、空但已聚焦、有内容(无论是否聚焦)。只写 input:not(:placeholder-shown) + label 会导致初始加载时 label 悬在顶部不动(因为 placeholder 还在显示,但 DOM 已渲染完毕)。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
推荐的状态组合写法:
input:placeholder-shown + label {
transform: translateY(0) scale(1);
color: #999;
}
input:focus + label,
input:not(:placeholder-shown) + label {
transform: translateY(-1.25rem) scale(0.85);
color: #007bff;
}
-
input:placeholder-shown + label覆盖初始空态(label 在框内) -
input:focus + label确保聚焦即上浮,哪怕还没输(提升反馈及时性) -
input:not(:placeholder-shown) + label保证填完后失焦也不回落 - 所有
label都要加pointer-events: none,否则会挡住 input 的点击热区
动态填充数据时 :not(:placeholder-shown) 不自动激活
编辑页回填、表单预设值、AJAX 加载后赋值……这些场景下,JS 设置了 input.value = "xxx",但 placeholder 仍存在,:placeholder-shown 伪类不会重新计算,label 依然卡在初始位置。
必须手动补发事件激活 CSS 状态:
const input = document.getElementById('name');
input.value = '张三';
input.dispatchEvent(new Event('input', { bubbles: true }));
- 只设
value不够,必须触发input事件(不是change) -
bubbles: true是关键,否则 Bootstrap 5 的.form-floating类无法捕获 - IE 完全不支持
:placeholder-shown,如需兼容,只能全量 JS 监听input和blur事件
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










