transition 在 :focus/:active 中不生效,主因是未声明属性初始值、:active 持续时间过短、或使用了不可过渡属性(如 visibility、display);需显式设初始值、用 max-height/opacity 替代、添加 tabindex 支持键盘 focus,并慎用 transition-delay。

transition 在 :focus 和 :active 中为何不生效
过渡动画在 :focus 或 :active 上“一闪而过”或完全没反应,通常不是 CSS 写错了,而是触发条件不满足:CSS 过渡要求「起始态和结束态都存在可过渡的属性值」,且浏览器能计算出变化过程。如果元素初始状态没有显式设置该属性(比如 opacity、transform),浏览器会从 auto 或 initial 开始过渡——而这些值无法参与过渡计算。
例如:div { transition: opacity 0.3s; } div:focus { opacity: 0.5; } 不生效,因为初始 opacity 没被声明,默认是 1,但浏览器可能未将其视为“已知起始值”,尤其在某些渲染上下文中。
- 始终为要过渡的属性设置明确的初始值(哪怕和默认值一致),如
opacity: 1、transform: translateX(0) -
:active状态极短(毫秒级),需确保过渡时长 ≤ 激活持续时间,否则动画来不及播放;建议搭配:focus或用 JS 扩展激活态 - 部分属性(如
display、height从auto变化)根本不可过渡,改用max-height或opacity + transform替代
如何让 transition 响应键盘 focus 而不只是鼠标点击
默认情况下, 对应 CSS 需同时定义初始态和聚焦态: 立即学习“前端免费学习笔记(深入)”; CSS 本身无法让 例如,一个下拉按钮: 此时点击下拉项后,只要焦点仍在菜单内,过渡就持续有效。 当用户先 hover 再快速点击, 真正难调的从来不是写几行 transition,而是理清状态切换时机、初始值声明、以及浏览器对伪类生命周期的处理边界。:focus 只对可聚焦元素(如 、、)生效,且需用户主动触发(Tab 键或点击)。若想让普通 tabindex 属性:
.card {
opacity: 1;
transform: scale(1);
transition: opacity 0.2s, transform 0.2s;
}
.card:focus {
opacity: 0.8;
transform: scale(0.95);
}
tabindex="0" 让元素进入标准 Tab 顺序;tabindex="-1" 则只能通过 JS .focus() 触发,不能用 Tab 键到达:focus 会自动移除,过渡反向执行——前提是初始态属性值已明确定义:focus 支持较弱,常需配合 ontouchstart 或监听 focusin 事件补全逻辑:hover 失效后如何保持 transition 效果(模拟“悬停锁定”)
:hover 状态持久化,但可通过组合伪类或 JS 实现近似效果。常见场景是:鼠标划过弹出菜单,希望移开后菜单延迟收起,而非立即消失。
:focus-within 替代 :hover,把容器设为可聚焦,并在子元素获得焦点时维持状态focusin / focusout 事件,给容器添加临时 class(如 is-open),再用 CSS 过渡这个 class 的样式mouseenter/mouseleave 并 toggle class——这容易因快速进出导致过渡中断;改用 setTimeout 加防抖,只在真正离开后才移除 class.dropdown-trigger:focus-within .dropdown-menu {
opacity: 1;
transform: translateY(0);
transition: opacity 0.2s, transform 0.2s;
}
.dropdown-menu {
opacity: 0;
transform: translateY(-8px);
transition: opacity 0.2s, transform 0.2s;
}
transition-delay 和 transition-duration 的实际影响差异
transition-delay 是等待多久才开始动画,transition-duration 是动画持续多久——但它们共同决定“何时可见变化”。容易被忽略的是:delay 不会阻塞后续状态切换。例如:a { transition: color 0.3s 0.1s; }
a:hover { color: red; }
a:active { color: blue; }
:active 会立即覆盖 :hover 的颜色,但因 delay 是 0.1s,hover 的红色甚至还没来得及出现,就被蓝色替代了。
transition-delay,统一设为 0 更可控:active 单独写 transition: color 0.05s(无 delay),覆盖全局过渡规则visibility 就不可过渡,即使写了 transition: visibility 0.3s 也无效










