【问题标题】:How can I delay the reset of hover until after transitions finish?如何将悬停的重置延迟到过渡完成后?
【发布时间】:2021-08-28 14:27:56
【问题描述】:

所以想象一下,你有 3 个彼此相邻的按钮。

在 CSS 中,你给它一个 3px 的边框样式,并且在悬停时边框会改变颜色。在渲染中,您会看到第一个孩子的顶部和底部、左侧和最后一个孩子的右侧,边框都是设置的 3px。但是在它的 6px 之间,因为两个按钮都有自己的边框。

让我们称之为Situation-a

所以要修复它,你可以让每个按钮(不是第一个按钮)都向左移动相同的 -3px,从而使其在视觉上共享相同的边框。

但是在悬停时,边框右侧的第一个按钮不会改变颜色,因为他旁边的按钮正在覆盖它。

让我们称之为Situation-b

但这两种解决方案都是错误的。应该发生的是,它们之间的边框仍然是 3px,并且在悬停时,无论女巫按钮如何,该 1 按钮周围的所有边框都会改变颜色。

但是你是怎么做到的?

z-index 添加到带有:hover 的按钮并不能解决问题,因为一旦您取消悬停,被重叠的边框会立即变回颜色,而其余边框会慢慢变回颜色。

基本上,彼此相邻的按钮需要共享相同的边框,并且在悬停时会更改相同边框的颜色,但不会产生 6px 的间隙。

这是两种情况的sn-p

* {
  padding: 0;
  margin: 0;
}
.parent {
  font-size: 0;
  margin: 10px;
}
.child {
  font-size: 24px;
  padding: 5px 15px;
  border-radius: unset;
  border: 3px solid black;
  background-color: lightgray;
  transition: border 0.25s ease-in-out;
}
.child:hover {
  border: 3px solid cyan;
}
.situation-b .child:not(:first-child) {
  margin-left: -3px;
}
Situation A (border between is 6px)
<div class="parent situation-a">
  <button class="child">action a</button>
  <button class="child">action b</button>
  <button class="child">action c</button>
</div>
Situation B (on button A hover, right border is not seen)
<div class="parent situation-b">
  <button class="child">action a</button>
  <button class="child">action b</button>
  <button class="child">action c</button>
</div>

这是该问题的在线创建示例:https://codesandbox.io/s/optimistic-dubinsky-1ji85?file=/index.html

【问题讨论】:

标签: html css


【解决方案1】:

您实际上可以使用 z-index 来做到这一点。您只需设置一个基本 z-index 并将过渡放在边框和 z-index 上。请参阅下面的示例,其中我夸大了转换时间,以便您可以看到它有效:

* {
  padding: 0;
  margin: 0;
}
.parent {
  font-size: 0;
  margin: 10px;
}
.child {
  font-size: 24px;
  padding: 5px 15px;
  border-radius: unset;
  border: 3px solid black;
  background-color: lightgray;
  transition: all 1s ease-in-out;
  position: relative;
  z-index:1;
}
.child:hover {
  border: 3px solid cyan;
  z-index:2;
}
.situation-b .child:not(:first-child) {
  margin-left: -3px;
}
Situation A (border between is 6px)
<div class="parent situation-a">
  <button class="child">action a</button>
  <button class="child">action b</button>
  <button class="child">action c</button>
</div>
Situation B (on button A hover, right border is not seen)
<div class="parent situation-b">
  <button class="child">action a</button>
  <button class="child">action b</button>
  <button class="child">action c</button>
</div>

【讨论】:

    【解决方案2】:

    如果您支持 CSS 网格,您可以执行以下操作:

    .buttons {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      column-gap: 3px;
      width: 300px;
      padding: 3px;
      background-color: black;
    }
    
    button {
      border: 0;
      outline: 3px solid transparent;
      transition: all 1s ease 0s;
    }
    
    button:hover {
      outline-color: cyan;
    }
    <div class="buttons">
      <button>action a</button>
      <button>action b</button>
      <button>action c</button>
    </div>

    说明

    包装元素.buttons 提供黑色作为背景。与 padding 和 column-gap 配合使用,看起来按钮有一个 3px 的边框。使用对文档布局没有影响的outline,以便在过渡期间允许重叠。


    你也可以用 flexbox 做到这一点:

    .buttons {
      display: flex;
      width: 300px;
      padding: 3px;
      background-color: black;
    }
    
    button {
      flex: 1;
      border: 0;
      outline: 3px solid transparent;
      transition: all 1s ease 0s;
    }
    
    button:not(:first-child) {
      margin-left: 3px;
    }
    
    button:hover {
      outline-color: cyan;
    }
    <div class="buttons">
      <button>action a</button>
      <button>action b</button>
      <button>action c</button>
    </div>

    【讨论】:

    • 虽然结果,在网格和 flex 中,情况都是完美的,但必须使用边框来完成,因为按钮本身来自第 3 方,我不允许剥离边框或更改它们的方式被渲染。它是要求的一部分。很抱歉没有在帖子中指定它。我仍然给你投赞成票,因为如果不满足要求,这将起作用
    • @Lith 总有一些东西 ;) 很高兴你能得到答案!
    【解决方案3】:

    回答如何在悬停时延迟“out”过渡:

    您也可以在转换属性中使用z-index。它不支持缓和其他属性的方式,但它确实支持转换延迟。

    * {
      padding: 0;
      margin: 0;
    }
    .parent {
      font-size: 0;
      margin: 10px;
    }
    button {
        position: relative;
      font-size: 24px;
      padding: 5px 15px;
      border-radius: unset;
      border: 3px solid black;
      background-color: lightgray;
        margin-right: -3px;
        z-index:1;
        transition: z-index 0s 1s, border 1s ease-in-out;
    }
    
    button:hover {
      border: 3px solid cyan;
        z-index: 10;
        transition: z-index 0s, border 1s ease-in-out;
    }
    <div class="parent">
      <button>action a</button>
      <button>action b</button>
      <button>action c</button>
    </div>

    解决布局问题的替代方法(下一个兄弟)

    由于延迟并不能解决实际的布局问题并且 z-index 存在问题,因此还有其他方法。也许这会帮助那些无法通过堆叠元素解决问题的人。

    在 CSS 中,我们可以使用 Next 兄弟选择器 (+) 来选择类型/类的 NEXT DOM 元素进行交互。

    * {
      padding: 0;
      margin: 0;
    }
    .parent {
      font-size: 0;
      margin: 10px;
    }
    button {
        position: relative;
      font-size: 24px;
      padding: 5px 15px;
      border-radius: unset;
      border: 3px solid black;
      background-color: lightgray;
        margin-right: -3px;
        z-index:1;
        transition: border 0.25s ease-in-out;
    }
    
    button:hover {
      border-color: cyan;
    }
    
    /* next element in the dom */
    button:hover + button {
        border-left-color: cyan;
    }
    <div class="parent">
      <button>action a</button>
      <button>action b</button>
      <button>action c</button>
    </div>

    注意:由于边框呈现的方式,这会导致较大边框宽度上出现奇怪的裁剪外观,因此我可能会使用 box-shadow 而不是边框​​来解决这个问题元素。

    【讨论】:

    • 遗憾的是,这会产生与 JPortillo 提到的相同的问题。第一个按钮 insta 的右边框淡入或淡出。这是imgur.com/a/8wO27ju 的 GIF 动图
    • 如果您在 z-index 过渡中添加延迟,则不会...我放慢了动画速度,以便您可以看到效果。
    • 遗憾的是,这仍然会产生问题。如果您将鼠标悬停在action b 按钮上,请等到完全过渡播放完毕,然后快速悬停到action a,然后按钮action a 的右边框将变黑一段时间。这是一个 gif:imgur.com/a/5yH80W3
    • @Lith 因为添加延迟并不能真正解决您的问题,这是另一种方法,将来可能会对您有所帮助。
    【解决方案4】:

    您实际上可以使用您的 z-index 想法来做到这一点。您必须只设置 position:absolute、position:relative 或 position:fixed 到元素才能工作:

    button {
          border: 4px solid black;
          height: 50px;
          width: 100px;
          border-radius: 0;
          margin-left: -8px;
          
          position: relative; /* Important */
    }
    
    button:hover {
          border: 4px solid blue;
          z-index: 2;
    }
    <div style="border-collapse: collapse;">
        <button>aa</button>
        <button>bb</button>
    </div>

    【讨论】:

    • 您省略了过渡。当您将其重新添加到您的解决方案中时,其他用户的答案会以同样的方式失败。
    【解决方案5】:

    我认为你缺少的只是position: relative;,所以z-index 被占用了。

    * {
      padding: 0;
      margin: 0;
      font-size: 0;
    }
    
    .parent {
      font-size: 0;
      margin: 10px;
    }
    
    .child {
      font-size: 24px;
      padding: 5px 15px;
      border-radius: unset;
      border: 3px solid black;
      background-color: lightgray;
      transition: border 0.25s ease-in-out;
      position: relative;
      z-index: 1;
    }
    
    .child:hover {
      z-index: 2;
      border-color: red;
    }
    
    .situation-b .child:not(:first-child) {
      margin-left: -3px;
    }
        <div class="parent situation-a">
          <button class="child">action a</button>
          <button class="child">action b</button>
          <button class="child">action c</button>
        </div>
        <div class="parent situation-b">
          <button class="child">action a</button>
          <button class="child">action b</button>
          <button class="child">action c</button>
        </div>

    【讨论】:

    • 如果您将鼠标悬停在按钮 A action a 上然后取消悬停,您会看到按钮 action a 的右侧立即变为黑色,而其余部分则慢慢变为红色。
    • 您一定错过了 OP 的要点,"使用 :hover 将 z-index 添加到按钮并不能解决问题,因为一旦您取消悬停,重叠的边框会立即变回颜色,而其余边框慢慢变回颜色。”
    • 你的回答错误的。当您将鼠标悬停时,右边框不会消失;它立即改变。
    • 如果你指的是我,那么不,我根本没有抄袭你。我提供了一个完整且有效的示例。
    • 确实不是你。我很抱歉。
    猜你喜欢
    • 1970-01-01
    • 2014-03-17
    • 2012-03-12
    • 2011-08-20
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    相关资源
    最近更新 更多