【问题标题】:Disable CSS animation on pseudo element inherited from parent在从父元素继承的伪元素上禁用 CSS 动画
【发布时间】:2015-11-10 21:22:22
【问题描述】:

标题几乎说明了一切,但这里是一个例子。

假设我有一个 CSS“加载微调器”,如下所示:

.spinner {
    height: 50px;
    width: 50px;
    position: relative;
    animation: rotate .6s infinite linear;
    border-left: 6px solid #222;
    border-right: 6px solid #222;
    border-bottom: 6px solid #222;;
    border-top: 6px solid #ccc;
    border-radius: 100%; 
}

@keyframes rotation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(359deg);
  }
}

我想为此添加一个伪元素 - 例如在 .spinner 之前或之后添加 content: 'loading...'

是否可以确保伪元素不从.spinner 继承动画,或者伪元素必须始终获取父元素的动画?

【问题讨论】:

  • 伪是子元素,所以当你旋转父元素时,子元素会自动旋转。我能想到的唯一解决方案是应用反向变换。
  • 您可以将微调器用作伪元素,将文本用作主要元素。看看这个jsfiddle.net/nicolaeolariu/uQ73y/1
  • @Chris;我不确定您是否打算将您的解决方案添加为答案,因此在我的答案中提到了它,并且还添加了一个 sn-p。如果您希望添加单独的答案,请告诉我,我会删除该部分。
  • 别担心@Harry,我的建议多于答案。

标签: css css-animations


【解决方案1】:

由于伪元素是父元素的子元素,只要父元素有动画,它就会继续旋转。即使在伪元素上设置animation: none 也没有效果。

让孩子看起来好像没有动画的唯一方法是反转效果,如下面的 sn-p 所示。所做的是将相同的动画添加到伪元素中,但将animation-direction 设置为reverse。这意味着伪得到精确的反向变换效果,因此会将其保留在相同的位置。

.spinner {
  height: 50px;
  width: 50px;
  position: relative;
  animation: rotation .6s infinite linear;
  border-left: 6px solid #222;
  border-right: 6px solid #222;
  border-bottom: 6px solid #222;
  border-top: 6px solid #ccc;
  border-radius: 100%;
}
.spinner:after {
  position: absolute;
  content: 'Loading..';
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
  animation: rotation .6s infinite linear reverse; /* added this line */
}
@keyframes rotation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(359deg);
  }
}
<div class='spinner'></div>

上面的 sn-p 使用 transform-origin 的默认设置 50% 50% 但如果子伪元素有 padding 和/或 margin 那么 transform-origin 设置必须相应地调整为避免伪元素产生类似颤抖的效果。计算逻辑在下面的sn-p中提供。

.spinner {
  height: 50px;
  width: 50px;
  position: relative;
  animation: rotation .6s infinite linear;
  border-left: 6px solid #222;
  border-right: 6px solid #222;
  border-bottom: 6px solid #222;
  border-top: 6px solid #ccc;
  border-radius: 100%;
}
.spinner.parent-padded-margin {
  padding: 10px;
  margin: 10px;
}
.spinner:after {
  position: absolute;
  content: 'Loading..';
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
  animation: rotation .6s infinite linear reverse;
  /* added this line */
}
.spinner.child-padded-margin:after {
  padding: 10px 8px;
  margin: 5px 4px;
  transform-origin: calc(50% - 12px) calc(50% - 15px);  /* calc(50% - ((padding-left + padding-right)/2 + margin-left)) calc(50% - ((padding-top + padding-bottom)/2 + margin-top)) */
}
.spinner.child-padded-margin-2:after {
  padding: 10px 6px 16px 14px;
  margin: 7px 12px 5px 10px;
  transform-origin: calc(50% - 20px) calc(50% - 20px);  /* calc(50% - ((padding-left + padding-right)/2 + margin-left)) calc(50% - ((padding-top + padding-bottom)/2 + margin-top)) */
}
@keyframes rotation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(359deg);
  }
}
<div class='spinner'></div>
<div class='spinner parent-padded-margin'></div>
<div class='spinner child-padded-margin'></div>
<div class='spinner child-padded-margin-2'></div>

定位伪元素(使用top,left,bottom,right)也会影响动画。它还需要相应地修改transform-origin,以使动画正常工作。下面的 sn-p 中有一个示例。

.spinner {
  height: 50px;
  width: 50px;
  position: relative;
  animation: rotation .6s infinite linear;
  border-left: 6px solid #222;
  border-right: 6px solid #222;
  border-bottom: 6px solid #222;
  border-top: 6px solid #ccc;
  border-radius: 100%;
}
.spinner.parent-padded-margin {
  padding: 10px;
  margin: 10px;
}
.spinner:after {
  position: absolute;
  content: 'Loading..';
  height: 100%;
  width: 100%;
  animation: rotation .6s infinite linear reverse;  /* added this line */
}
.spinner.child-positioned{
    margin-bottom: 40px;
  }
.spinner.child-positioned:after {
  top: 120%;
  left: 2%;
  transform-origin: calc(50% - 2%) calc(50% - 120%); /* basically need to subtract the distance from the left and top of the container */
}
.spinner.child-positioned-negative:after {
  bottom: -120%;
  right: -2%;
  transform-origin: calc(50% - 2%) calc(50% - 120%); /* basically need to subtract the distance from the left and top of the container */
}
@keyframes rotation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(359deg);
  }
}
<div class='spinner child-positioned'></div>
<div class='spinner child-positioned-negative'></div>

注意:上述两种解决方案在最新版本的 Chrome、Opera 和 Safari 中都可以正常工作,但会导致文本在 IE 11、Edge 和 Firefox 中出现倾斜。 Firefox 似乎需要一个单独的动画,从 FF 的旋转(-10deg)到旋转(-370deg),而它在 IE 中变得更加复杂。


没有在伪(子)元素上设置反向动画的唯一替代方法是使用 Chris 在他的评论中提到的 方法。这意味着将边框和动画直接设置为伪元素。这意味着父级的内容不会受到影响,因为父级不会受到子级转换的影响。

.spinner {
  height: 50px;
  width: 50px;
  position: relative;
}
.spinner:after {
  position: absolute;
  content: '';
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
  animation: rotation .6s infinite linear;
  border-left: 6px solid #222;
  border-right: 6px solid #222;
  border-bottom: 6px solid #222;
  border-top: 6px solid #ccc;
  border-radius: 100%;
}
@keyframes rotation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(359deg);
  }
}
&lt;div class='spinner'&gt;Loading...&lt;/div&gt;

【讨论】:

  • 虽然此解决方案在技术上确实回答了我的问题,但它不是一个理想的解决方案,因为与 :after 上给定位置的任何偏差(包括使用边距和填充)都会导致伪元素 - 在这种情况下文本 - 向微调器的方向移动 - 尽管保持水平外观。
  • @Rob 是的,这不是理想的解决方案,但没有其他解决方案(除非您希望采纳 Chris 的建议)。而且,如果你能告诉我定位的文本,我可以帮助调整它以使用此代码。
  • @Harry,你好。你能展示如何在(中心)圆圈内制作文字吗?例如“OK”消息
  • 它对我不起作用。但是我只是添加了与父级相同的动画,但将动画时间设置为 5ms,并且动画根本不可见
【解决方案2】:

为了问题的完整性以及@Harry 的全面答案,我制作了一个版本,其中包含微调器下方的文本。这样做的方法是将.spinner作为画布,将实际旋转的圆圈:beforeloading...放在:after中如下:

.spinner:before {
    content: ' ';
    display: block;
    height: 50px;
    width: 50px;
    margin: 24px auto 6px auto;
    animation: rotation .6s infinite linear;
    border-left: 6px solid #222;
    border-right: 6px solid #222;
    border-bottom: 6px solid #222;;
    border-top: 6px solid #ccc;
    border-radius: 100%;
}
.spinner {
  height: 100px;
  width: 100px;
  position: relative;
}
.spinner:after {
  display: block;
  text-align: center;
  content: 'loading...';
}
@keyframes rotation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(359deg);
  }
}
&lt;div class='spinner'&gt;&lt;/div&gt;

【讨论】:

  • 看起来不错。出于某种原因,我只是假设您想要圆圈内的文字:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 1970-01-01
  • 2011-09-29
  • 2017-04-27
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多