:placeholder-shown是判断placeholder是否显示的状态开关,真正浮动的是label;需input含placeholder属性、label与input正确关联且设position: relative,配合:not(:placeholder-shown)和:focus-within等实现全状态控制。
:placeholder-shown 本身不实现“悬浮占位符效果”,它只是个状态开关——真正悬浮的是 label,而 :placeholder-shown 告诉浏览器:“现在 placeholder 正在显示,说明输入框为空”。这个判断比 :focus 或 JS 判断 value === "" 更可靠,也更轻量。
:placeholder-shown
这个伪类不是“检测内容是否为空”,而是“检测浏览器是否正在渲染 placeholder 文本”。没有 placeholder 属性(哪怕值是空字符串 placeholder=""),浏览器根本不会启用占位逻辑,:placeholder-shown 永远为 false。
placeholder=" "(空格)和 placeholder="" 都合法,但后者更干净,避免空格被误读为真实提示文本placeholder 必须写在 HTML 中,JS 动态设置(如 input.setAttribute('placeholder', ''))在部分旧版 Safari 中无法触发伪类placeholder 属性后,哪怕 input 值为空,:placeholder-shown 也不匹配——这不是 bug,是规范行为:placeholder-shown 和 :not(:placeholder-shown) 的实际分工浮动标签的两个关键状态靠它们区分:
input:placeholder-shown + label → label 保持原始位置(沉底)input:not(:placeholder-shown) + label → label 上浮缩放(已输入或失焦但非空):not(:placeholder-shown) 规则必须写在 :placeholder-shown 之后,否则会被覆盖:placeholder-shown 立即失效——这是它比 JS trim() 更底层的优势,也是陷阱:粘贴不可见字符会导致“看似空,实则不浮”:placeholder-shown 实现完整浮动逻辑它只回答“placeholder 是否正显示”,不回答“有没有焦点”或“是否通过校验”。常见组合缺一不可:
立即学习“前端免费学习笔记(深入)”;
input:focus-within + label → 解决“空但已聚焦,label 应上浮”的场景input:valid + label → 覆盖 required 字段校验通过后的固定上浮态:placeholder-shown 无法区分“空且聚焦”和“空且未聚焦”,视觉上会漏掉一次关键动画::-webkit-input-placeholder 回退样式真正容易被忽略的点是:浮动效果依赖 label 的定位上下文。没给 label 设 position: relative,transform: translateY() 就会以视口为基准偏移,导致标签“飘出屏幕”。这不是动画写错了,是定位链断了。