:placeholder-shown不能单独实现浮动标签,因其仅在input有placeholder且内容为空(不含空格等)时匹配,用户聚焦或输入即失效,无法覆盖“空但聚焦”“非空失焦”等关键状态,须配合:focus、:not(:placeholder-shown)等组合使用。

:placeholder-shown 本身不实现浮动标签,它只是个“空状态”开关——真正上浮的是 label,靠它来触发样式切换而已。单靠这个伪类,标签根本不会动。
为什么:placeholder-shown不能单独控制浮动
它只在 input 有 placeholder 属性且内容为空(连空格都不能有)时才匹配。用户一聚焦、一输入、甚至粘贴个全角空格,:placeholder-shown 就立刻失效,label 会掉回原位——而浮动标签要求“聚焦时上浮”“输入后保持上浮”,这三类状态它一个都覆盖不了。
-
:placeholder-shown不响应:focus,无法捕获“空但已点击”的瞬间 -
:not(:placeholder-shown)能识别“已输入”,但无法区分“失焦”和“聚焦”两种视觉需求 - IE 完全不支持;Safari ≤15.4 偶发失效;旧 Edge 需 16+ 才可用
input + label 结构必须严格相邻
所有基于 + 的选择器(比如 input:focus + label)都依赖 DOM 顺序:label 必须紧跟在 input 后面,中间不能插任何元素(图标、错误提示、span 等)。否则规则压根不生效。
- ✅ 正确:
<input placeholder="邮箱"><label>邮箱</label> - ❌ 错误:
<label>邮箱</label><input placeholder="邮箱">(+只选后继,不选前驱) - ❌ 错误:
<input><span class="icon"></span><label>邮箱</label>(+要求紧邻)
必须写 placeholder 属性,哪怕值为空
没有 placeholder 属性,:placeholder-shown 永远为 false——这不是 bug,是规范行为。JS 动态设置(如 input.setAttribute('placeholder', ''))在部分旧版 Safari 中也不触发。
- 推荐写法:
placeholder="",干净且合法 - 避免写
placeholder=" "(空格),容易被误判为真实提示文本 -
type="hidden"、disabled或contenteditable元素上,该伪类无效
label 必须设 position: relative
浮动靠 transform: translateY() 实现,但若 label 没设 position: relative,偏移基准就是视口,标签会“飘出屏幕”。这是最容易忽略、也最难调试的定位问题。
- 别漏掉:
label { position: relative; } - 记得加
pointer-events: none,否则 label 会挡住 input 点击 - 动画要加
transition,否则上浮是瞬移,不是“浮动”
真正难的不是写对那几行 CSS,而是理解 :placeholder-shown 只是一个信号源——它不负责逻辑判断,也不管焦点或校验。所有状态组合(空+聚焦、非空+失焦、非空+聚焦)都要手动覆盖,漏掉任意一种,UI 就会卡在奇怪的位置。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











