先记住这个答案
:placeholder-shown 关注的是占位提示是否正在显示,而不是表单值是否合法。空文本框写了 placeholder 时通常命中;输入内容后不命中,:not(:placeholder-shown) 可用于浮动标签样式。但没有占位提示的空框、只输入了空格的框、或不支持占位的控件,都不能简单用这条伪类判断“用户已填写”。
- 需要占位提示才可能命中
- 输入值出现后通常不再命中
- 空格也是输入内容
- 校验状态应看
:valid或:invalid
浮动标签为什么常用它
设计希望输入为空时标签出现在框内,输入后标签移到上方。占位状态可触发这个视觉切换,但真实标签仍要用 <label>,不能只放一个会消失的 placeholder。
<label class="field">
<input id="city" name="city" placeholder=" " required>
<span>城市</span>
</label>
<style>
.field input:not(:placeholder-shown) + span { transform: translateY(-1.2rem); }
</style>这里的空格占位只是让伪类有可显示的提示状态;真正给字段命名的是可见文本与标签元素。用户输入后,伪类不再命中,标签位置改变。 页面初始已有值时也会进入“不显示占位”的状态,正好避免标签盖住预填内容。但“有值”不等于“合法”,例如 URL 格式错误仍可能不显示占位。
别用占位状态替代校验
:placeholder-shown 与 :invalid 的判断基准不同。一个必填框空着可能既显示占位又无效;用户输一个空格后占位消失,但业务上可能仍要拒绝全空白内容。
要表示必填、格式和范围错误,应使用原生约束、:valid、:invalid 或脚本读取 validity。占位文案最好是示例或短提示,不要把完整填写要求藏在里面,因为开始输入后它就消失。
浮动标签常用 input:not(:placeholder-shown) 判断“当前有值”,但它依赖输入框确实设置了 placeholder。没有占位文本时,不要假设选择器仍能代表空值状态。浏览器自动填入的值也要实测:页面初始化、自动填充、用户删除输入,都可能让标签位置改变。让标签始终可见比把唯一字段名藏进 placeholder 更稳,因为占位文字会在输入后消失,不能代替 <label>。
容易答错的地方
- 认为没有
placeholder的空框也会命中 - 伪类要求占位提示处于显示状态;没有占位提示就不能靠它识别空值。
- 把
:not(:placeholder-shown)当作有效值 - 它只说占位没显示,无法证明输入满足格式或业务规则。
面试官还会怎么问?
只输入一个空格时会怎样?
输入框已有内容,占位通常不显示;需要拒绝空白字符串时应单独校验。
浮动标签可以完全用 placeholder 吗?
不建议。<label> 提供稳定名称,placeholder 输入后消失,不能替代字段标签。
type="number" 的占位状态能统一依赖吗?
不同控件的占位支持和呈现可能不同,设计前要在目标浏览器实际测试,别把该伪类当成所有输入类型的通用状态。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。