:placeholder-shown仅在input/textarea有placeholder且为空、未聚焦、未输入时生效;失效主因是dom值非空(如空格、value=""、框架绑定空字符串)或兼容性问题。

:placeholder-shown 只在 <input> 或 <textarea></textarea> 有 placeholder 且**当前为空值、未获得焦点、未输入任何内容**时才生效。它不是“只要写了 placeholder 就一直显示”,也不是“聚焦后自动隐藏”——这是最常误解的起点。
为什么 :placeholder-shown 没反应?常见失效场景
多数人写完 CSS 却看不到效果,根本原因在于触发条件被悄悄破坏:
- 输入框已预填了空格或
—— 浏览器认为“非空”,:placeholder-shown不匹配 - 用了
value="xxx"属性(哪怕值为空字符串value="")—— 部分浏览器(如 Safari)会视为“受控组件”,跳过 placeholder 状态判断 - 表单用了 React/Vue 的双向绑定(如
v-model或value={xxx}),但初始 state 不是undefined或null,而是空字符串""—— DOM 值非空,状态不触发 - CSS 选择器权重不够,被其他规则覆盖(比如
.input:focus + label强行显隐,干扰了基于 placeholder 的逻辑)
极简标签隐藏:用 :placeholder-shown 控制 <label></label> 显隐
典型做法是把 <label></label> 放在 <input> 后面(HTML 顺序),用相邻兄弟选择器 + :placeholder-shown 实现「有内容时 label 上浮隐藏」:
<div class="field"> <input type="text" placeholder="邮箱"><label>邮箱</label> </div>
CSS 关键部分:
.field label {
position: absolute;
top: 0;
left: 0;
opacity: 0.6;
transition: all 0.2s ease;
}
.field input:placeholder-shown + label {
opacity: 1;
}
.field input:not(:placeholder-shown) + label,
.field input:focus + label {
font-size: 0.8em;
top: -1.2em;
opacity: 0.9;
}
注意::not(:placeholder-shown) 才代表“已输入”或“已失焦但非空”,不能只靠 :focus 判断——用户可能聚焦后又点走,但没输内容,此时 label 仍应保持上浮态。
兼容性与降级处理要点
:placeholder-shown 在 Chrome 47+、Firefox 51+、Edge 79+ 支持良好,但 Safari 9–13.1 存在 bug:当 input 为 type="number" 或含 pattern 时,placeholder 状态可能不更新。应对方式:
- 避免对
type="number"或type="email"强依赖:placeholder-shown控制 label;改用 JS 监听input和blur事件手动加 class - 需要兼容老 Safari?可加一层兜底:
.field input:not([value='']) + label(但仅适用于初始无 value 属性的场景) - 别用
!important强撑样式——它会让后续 JS 动态控制变得不可预测
真正难的不是写对那几行 CSS,而是确保 input 的“空值语义”始终干净:不带空格、不预设 value、不被框架悄悄注入默认字符串。一旦 DOM 值和视觉状态错位,:placeholder-shown 就彻底失效,而这种错位往往在表单嵌套多层后才暴露。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











