:placeholder-shown不能直接驱动浮动标签,因其仅在placeholder显示时生效,不感知聚焦或非空状态,输入空格、js清空placeholder或预设value均致其失效,必须配合:focus-within或javascript监听才能覆盖全部交互状态。

为什么 :placeholder-shown 不能直接做浮动标签
因为 :placeholder-shown 只在输入框有 placeholder 且内容为空时生效,一旦用户开始输入、或者 placeholder 被 JS 清空(比如 input.placeholder = ''),这个伪类就立刻失效——它不感知“是否聚焦”,也不感知“是否非空”,只认 placeholder 是否正显示。所以单靠它无法稳定触发标签上浮。
必须配合 :focus-within 或 JS 监听才可靠
实际项目中浮动标签需要响应两个状态:输入框获得焦点(哪怕为空),或已有内容(哪怕失焦)。纯 CSS 方案得用父容器包裹 input 和 label,再用 :focus-within 覆盖聚焦态,:placeholder-shown 补充空值态:
<div class="field"> <label>邮箱</label> <input type="email" placeholder=" "> </div>
关键点:
- placeholder 设为空格而非空字符串,否则
:placeholder-shown不触发(浏览器忽略空 placeholder) - label 默认绝对定位,top 偏移;当
.field:focus-within label或.field input:placeholder-shown + label时,改 top / transform / font-size - Chrome/Firefox 支持
:focus-within,Safari 15.4+ 才完全支持;旧 Safari 必须降级用 JS
:placeholder-shown 的兼容性陷阱
这个伪类在 Safari 14.1–15.3 中存在严重 bug:当 input 设置了 value 属性(哪怕为空字符串),:placeholder-shown 永远不会匹配——哪怕 DOM 里 placeholder 还在、且输入框视觉上是空的。现象是标签卡在下方不上浮。
解决办法只有两个:
- 彻底避免设置
value属性(用input.value = ''动态赋值,而不是写 HTMLvalue="") - 检测 Safari 旧版本,对
:placeholder-shown规则加@supports not selector(:placeholder-shown)回退
别用 transition 直接动 top,改用 transform
浮动标签如果靠 top: -20px + transition: top .2s 实现,会触发 layout,滚动时可能卡顿。正确做法是:
- label 初始
transform: translateY(0) - 激活态设
transform: translateY(-24px) scale(0.85) - transition 写全:
transform .2s cubic-bezier(0.4, 0, 0.2, 1), opacity .15s - 务必加
will-change: transform(尤其 iOS Safari)
真正难的不是怎么写 CSS,而是处理 placeholder 被清空、value 被预设、focus 状态被第三方库劫持这些边缘情况——这些地方一漏,标签就卡死在错误位置。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











