【问题标题】:Weird behavior when rotating an element on hover悬停时旋转元素时的奇怪行为
【发布时间】:2019-03-06 11:15:14
【问题描述】:

给出这两个例子。

使用悬停

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transition: transform 2s;
  transform: translateX(-50%);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
}

div:hover {
  transform: translateX(-50%) rotate(var(--deg));
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>

使用动画

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transform: translateX(-50%);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
  animation: rotate 2s linear 2s;
}

@keyframes rotate {
  to {
    transform: translateX(-50%) rotate(var(--deg));
  }
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>

如您所见,rotate(180deg) 和 rotate(-180deg) 动作相同,rotate(360deg) 根本不动。

问题是如果你让它逐渐移动它会正常运行。

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
}

div:hover {
  animation: rotate 2s linear;
}

@keyframes rotate {
  0% {
    transform: translate(-50%, -50%) rotate(0deg);
  }
  25% {
    transform: translate(-50%, -50%) rotate(45deg);
  }
  50% {
    transform: translate(-50%, -50%) rotate(90deg);
  }
  75% {
    transform: translate(-50%, -50%) rotate(135deg);
  }
  100% {
    transform: translate(-50%, -50%) rotate(180deg);
  }
}
&lt;div&gt;&lt;/div&gt;

我找到的解决方案是将translate(-50%, -50%)替换为不一致的margins

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transition: transform 2s;
  /* Minus half the width, hard coded not a good idea*/
  margin: 0 0 0 -75px; 
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
}

div:hover {
  transform: rotate(var(--deg));
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>

所以主要问题是为什么会发生这种奇怪的行为?

编辑:不只是寻找一个快速的答案(你可以看到有两个可用的),而是一个解释:)

【问题讨论】:

  • 该错误似乎已修复

标签: css css-transitions css-transforms


【解决方案1】:

2021:错误不再发生

这似乎是一个浏览器错误(至少在 Chrome 上),因为如果您在 Firefox 上尝试该代码,它可以正常工作。

让我们参考 the specification 来解释这一点。以下是变换之间的插值应该如何工作的所有不同情况。

在我们的例子中,我们将考虑最后一点,我们没有相同数量的转换函数,浏览器应该通过从缺失列表中添加身份转换函数来处理这个问题,在我们的例子中它应该是 @987654324 @。

所以从技术上讲,从translate(-50%) 到translate(-50%) rotate(360deg) 的转换应该与从translate(-50%) rotate(0) 到translate(-50%) rotate(360deg) 的转换相同。

除非我遗漏了一些东西,这肯定是一个错误,例如单独使用rotate(360deg) 时,Chrome 使用第二点(当一个值为none)处理这个问题,这几乎是一样的作为最后一点。

【讨论】:

  • 我明白了,只是 chrome 没有遵循规范,我想我们不能再依赖浏览器来清理我们,谢谢 :)
  • @ZohirSalakCeNa 或者您可以将此作为错误报告给 chrome 团队;)它可能会得到修复,因为这是一个非常特殊的情况
  • 我一定会调查的。
【解决方案2】:

你需要设置一个初始的rotate(0),这样两个状态之间才能有动画。将div 的初始变换设置为:

transform: translateX(-50%) rotate(0);

过渡:

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transition: transform 2s;
  transform: translateX(-50%) rotate(0);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
}

div:hover {
  transform: translateX(-50%) rotate(var(--deg));
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}

body {
  overflow: hidden;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>

动画:

div {
  position: absolute;
  width: 150px;
  height: 40px;
  background: orange;
  left: 50%;
  top: var(--top);
  transform: translateX(-50%) rotate(0);
  text-align: center;
  line-height: 40px;
  font-size: 1.2em;
  animation: rotate 2s linear 2s forwards;
}

@keyframes rotate {
  to {
    transform: translateX(-50%) rotate(var(--deg));
  }
}

div:nth-child(1) {
  --deg: 180deg;
  --top: 20%;
}

div:nth-child(2) {
  --deg: -180deg;
  --top: 40%;
}

div:nth-child(3) {
  --deg: 360deg;
  --top: 60%;
}

body {
  overflow: hidden;
}
<div>180deg</div>
<div>-180deg</div>
<div>360deg</div>

【讨论】:

  • 如果我使用边距来定位 div,则不需要rotate(0),为什么?
  • 我只能猜测,当transform根本没有初始化的时候,变化就被正确检测到了。
  • 是的,我想知道为什么会这样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多