伪类 `:checked` 的视图过渡不起作用

前端开发 2026-07-08

我有一个 视图过渡

checkbox.oninput = () => {
  document.startViewTransition(() => {
    checkbox.classList.toggle('checked');
  });
};
.container {
  display: grid;
  grid-template: 100px 100px / 100px 100px;
}

label {
  view-transition-name: foo;
}

:has(.checked) {
  grid-column: 2;
  grid-row: 2;
}
<div class="container">
  <label>
    <input type="checkbox" id="checkbox" oninput="">
    Click here
  </label>
</div>

但我不喜欢这段代码。我想在CSS选择器中使用 :checked 伪类,而不是使用冗余的 .checked 类并保持同步。那样会更地道。当我用 :checked 代替 .checked 时,视图过渡就不会发生。这个问题该如何修复?

解决方案

问题在于,在你调用 document.startViewTransition() 的时候,:checked 规则已经被应用。你需要在即将触发 input 事件之前就挂上一个事件监听。虽然存在一个 beforeinput 事件,但它只适用于文本可编辑输入中的键盘输入,而不适用于复选框。

因此,换一种仍然有些丑陋的方法:在输入事件中,同步地抵消输入的 checked 值,这样 :checked 就能与之前的状态相匹配。然后启动过渡,在其更新回调中,把 checked 属性重新设回它本来要变成的值。现在过渡已经掌握了它所需的一切信息:

checkbox.oninput = e => {
  if (document.startViewTransition) {
    checkbox.checked = !checkbox.checked;
    document.startViewTransition(() => {
      checkbox.checked = !checkbox.checked;
    });
  }
}
.container {
  display: grid;
  grid-template: 100px 100px / 100px 100px;
  label {
    view-transition-name: foo;
    &:has(:checked) {
      grid-column: 2;
      grid-row: 2;
    }
  }  
}
<div class="container">
  <label>
    <input type="checkbox" id="checkbox" oninput="">
    Click here
  </label>
</div>
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章