不能只用:valid或:placeholder-shown单独控制浮动标签,因:valid依赖required等验证属性,无约束时空值也视为valid;:placeholder-shown在用户聚焦或输入空格时立即失效,但标签应保持上浮;两者均无法覆盖“空且聚焦”“非空”“空且未聚焦”全部状态。
:valid 或 :placeholder-shown 单独控制浮动标签:valid 依赖表单验证逻辑,比如 required、type="email" 或 pattern;没有这些约束时,空值也视为 valid,标签就永远不会上浮。而 :placeholder-shown 只在 placeholder 正显示时为 true——用户一聚焦或输入一个空格,它立刻失效,但此时标签理应保持上浮。两者单独用都会漏掉关键状态。
:valid 和 :placeholder-shown 怎么组合才覆盖全部场景必须同时响应三种状态:空且聚焦、非空(无论是否聚焦)、空且未聚焦。推荐这样写:
input:placeholder-shown + label → 标签沉底(初始态)input:focus + label → 空但已点击,标签上浮input:valid + label → 有内容且通过校验,标签固定上浮注意顺序::placeholder-shown 规则必须放在最后,否则会被前面的 :focus 或 :valid 覆盖。另外,:valid 在 input 值为 "0"(数字框)、" "(空格)时可能不触发,不如 :not(:placeholder-shown) 稳定。
浮动标签不是纯 CSS 魔术,它对 DOM 结构很敏感:
立即学习“前端免费学习笔记(深入)”;
+ 选择器才能生效placeholder 属性(哪怕写成 placeholder=""),否则 :placeholder-shown 永远不匹配required,:valid 才有意义;没加 required 却指望 :valid 判断“是否有输入”,基本无效常见错误:把 label 放 input 前面、中间插了个图标、或者 JS 动态设置 placeholder —— 这些都会让伪类失效。
:valid 和 :placeholder-shown 在 IE 中完全不支持,Edge 16+、Chrome 57+、Firefox 51+、Safari 15.4+ 才可用。更麻烦的是边界行为:
:placeholder-shown 会失效,但 value 实际仍是“空”:valid 对 type="number" 输入 "0" 默认不触发(因为 0 是有效数字),但业务上可能要求“非空”,这时 UI 和校验逻辑就错位了:valid 能保持上浮,但若字段非必填又没 pattern,:valid 就不可靠,得 fallback 到 :not(:placeholder-shown)
真正健壮的做法不是二选一,而是把 :not(:placeholder-shown) 当主力,:valid 仅作补充校验层——毕竟 CSS 层面没法做 trim 或正则匹配,能依赖的只有浏览器渲染 placeholder 的那一刻。