:placeholder-shown 是轻量级空状态视觉代理,仅在 input/textarea 的 value 为空且存在 placeholder 属性时生效;它不控制提示语显隐,而是通过 CSS 选择器(如 :placeholder-shown + .hint)触发样式切换,需配合 :focus-within 区分交互状态,并用 JS 校验全角空格等边界情况。

:placeholder-shown 本身不控制提示语,它只反映 placeholder 是否正在显示;真正控制提示语显隐的,是你用它写的 CSS 选择器组合。
为什么 :placeholder-shown 能当“空状态开关”用
它在 input 或 textarea 的 value 为空(trim() 后)且 placeholder 属性存在时生效。浏览器渲染逻辑决定 placeholder 是否“露脸”,而这个露脸状态恰好和用户未输入高度重合——所以它成了最轻量的空值视觉代理。
但要注意:
-
:placeholder-shown不等于value === "":JS 手动设input.value = ""后若没触发重绘,伪类可能滞后 - 没有
placeholder属性,哪怕value是空的,伪类也永不匹配 -
type="number"在部分旧 Chrome 中不触发该伪类,建议先用type="text"验证逻辑
:placeholder-shown + .hint 是最可靠的选择器写法
想让提示文字随输入框状态切换显隐,必须用相邻兄弟选择器(+),且 .hint 元素得紧接在 input 后面。伪元素(如 ::after)不能加在 input 上,因为它是替换元素。
立即学习“前端免费学习笔记(深入)”;
正确结构示例:
<div class="field"> <input type="text" placeholder="请输入邮箱"> <small class="hint">用于登录和找回密码</small> </div>
CSS 写法:
.field .hint { opacity: 0.4; }
.field input:placeholder-shown + .hint { opacity: 1; }
.field input:focus:not(:placeholder-shown) + .hint { opacity: 0.6; }
关键点:
- 不要写
input:placeholder-shown::after—— 它无效 - 避免嵌套过深,比如
.form-group input:placeholder-shown + label,某些浏览器渲染会延迟 - 如果提示语要完全隐藏,用
display: none;若需过渡动画,优先改opacity+visibility,别用display
配合 :focus-within 区分三种交互状态
单靠 :placeholder-shown 只能判断“空”,但表单需要区分:空且未聚焦 → 空且正编辑 → 已输入。这时得靠父容器的 :focus-within。
典型组合逻辑:
-
.field input:placeholder-shown + .hint:空且未聚焦(提示语全显) -
.field:focus-within input:not(:placeholder-shown) + .hint:已输入(提示语弱化) -
.field:focus-within input:placeholder-shown + .hint:空但正聚焦(提示语保持可见,边框可变色)
注意::focus-within 在 Safari ≤15.4 有兼容问题,需降级为 JS 监听 focusin/focusout。
真正难的是边界情况:用户粘贴全角空格、零宽字符、或自动填充带不可见前缀的值——这些都会让 :placeholder-shown 提前退出,但表单语义上仍是空的。CSS 做不到这点,必须靠 JS 的 el.value.trim() === "" 校验兜底。


















