:placeholder-shown仅在input内容为空字符串且placeholder可见时生效,非检测placeholder属性是否存在;受控组件需同步value,移动端及number/search类型兼容性差。

placeholder-shown伪类只对空值生效,不是“有无占位符”
很多人以为 :placeholder-shown 是检测 input 是否设置了 placeholder 属性,其实它只在输入框**内容为空且 placeholder 可见时**才匹配。一旦用户输入哪怕一个空格,或者 focus 后清空但光标还在,都可能不触发——尤其当 input 有默认 value 或受控于 JS 时,样式会意外失效。
常见错误现象:input:placeholder-shown { border: 2px solid #ccc; } 在 React 表单里点一下就消失,或输入空格后 border 不恢复。
- 必须确保 input 的
value确实为空字符串(""),而非null、undefined或带空格的字符串 - React/Vue 中若用受控组件,要同步更新 DOM 的
value属性,否则:placeholder-shown不响应 state 变化 - 移动端 Safari 对
:placeholder-shown支持较晚(iOS 12.2+),旧版本直接不生效
想根据真实输入长度动态变样式?别只靠placeholder-shown
:placeholder-shown 本质是“空状态开关”,不是长度探测器。它无法区分 "" 和 "a",更不能响应 "ab".length > 5 这类条件。真要按长度控制样式,得组合其他手段。
- 纯 CSS 方案:用
input:not(:placeholder-shown):valid配合pattern和required做粗略分段(如至少 6 位密码),但粒度有限 - JS 辅助更可靠:监听
input事件,动态加 class,比如input.length-0/input.length-5/input.length-10 - 注意防抖:频繁输入时避免每键都重排样式,
requestAnimationFrame比setTimeout更稳
placeholder-shown + :focus-within 能覆盖多数交互场景
单独用 :placeholder-shown 容易漏掉“已输入又删空但仍有焦点”的情况。配合 :focus-within(父容器含聚焦子元素)能补全视觉反馈链。
立即学习“前端免费学习笔记(深入)”;
例如表单组需要“空时灰边框,聚焦时蓝边框,有内容时绿边框”:
label.input-group:has(input:placeholder-shown) input {
border-color: #ddd;
}
label.input-group:focus-within input {
border-color: #007bff;
}
label.input-group:not(:has(input:placeholder-shown)) input {
border-color: #28a745;
}
-
:has()目前 Chrome 105+/Safari 15.4+/Firefox 121+ 支持,老浏览器需降级为 JS 判断 - 不用
:focus直接写 input,是因为 label 包裹时焦点实际在 label 上,:focus-within更准确 - 避免同时用
:placeholder-shown和:valid冲突:前者依赖空值,后者依赖校验,逻辑不同源
placeholder-shown 的兼容性坑比想象中多
看似简单的伪类,在真实项目里常因环境差异翻车。最典型的是 type="number" 或 type="search" —— 大部分浏览器根本不支持这些类型上的 :placeholder-shown。
- Chrome 对
type="number"完全忽略:placeholder-shown,即使 placeholder 渲染出来了 - Firefox 在
type="search"中表现正常,但 Safari 会跳过该伪类 - 如果 input 被设为
readonly或disabled,:placeholder-shown永远不匹配,哪怕 placeholder 文本还显示着 - 测试时务必用真实设备+主流浏览器组合验证,不能只信 Can I Use 的“支持”标记
真正难的不是写对一行 CSS,而是确认它在所有目标环境下都按预期响应输入状态变化。尤其是混合了 JS 控制、表单库封装、移动端软键盘弹出等场景,:placeholder-shown 很容易变成“看起来有效,上线就失效”的隐形陷阱。










