悬停时强制结束 CSS 过渡

Force end CSS transition on hover

默认情况下,如果您停止将鼠标悬停在某个元素上,则所有属性的转换也会停止。简单示例:

li {
  position: relative;
  transition: 1s;
  left: 0;
}

li:hover {
  left: 20px;
}
<ul>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
</ul>

尝试运行指针从列表的顶部快速指向底部,元素几乎不会移动。我想实现过渡时的行为,一旦开始,就会结束。我正在寻找纯粹的 CSS 解决方案。

不确定这是否可以仅通过 css 实现,我会为此使用 Javascript 并在转换完成后收听。

let listItems = document.querySelectorAll('li');

listItems.forEach(listItem=>{
  listItem.addEventListener('mouseover', function() {
    this.classList.add('slide-left');
  });
  
  listItem.addEventListener('transitionend', function() {
    this.classList.remove('slide-left');
  });
})
li {
  position: relative;
  transition: 1s;
  left: 0;
}

li:hover, .slide-left {
  left: 20px;
}
<ul>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
</ul>

如前所述,纯 CSS

无法做到这一点

但是这里有一个 hack 需要嵌套并且不适用于多个兄弟姐妹并且如果鼠标移出文档。

body {
  overflow: hidden;
}

[ctr] {
  display: inline-block;
}

[box] {
  width: 80px;
  height: 80px;
  background: red;
  position: relative;
  transition: 1s;
  left: 0;
}

[ctr]:hover {
  left: 20px;
  width: 9999px;
  height: 9999px;
  animation: resetctr 1s 1s linear forwards;
}

[ctr]:hover>[box] {
  left: 20px;
  animation: resetbox 1s 1s forwards;
}

@keyframes resetbox {
  from {
    left: 20px;
  }
  to {
    left: 0;
  }
}

@keyframes resetctr {
  to {
    width: auto;
    height: auto;
  }
}
<div ctr>
  <div box></div>
</div>

一个简单的 CSS 解决方案是考虑一个伪元素,该元素将在过渡期间覆盖整个屏幕以允许它结束:

li {
  position: relative;
  transition: 2s;
  left: 0;
}

li:hover {
  left: 20px;
}

li:before {
  content:"";
  position:fixed;
  inset:0 0 100%;
  z-index:999;
}
li:hover:before {
  animation:h 1s;
}

@keyframes h{
  0%,98% {inset:0;}
}
<ul>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
  <li>Item</li>
</ul>