禁用从父级继承的伪元素上的CSS动画

Rob*_*zyc 5 css css3 css-animations

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

假设我有一个CSS'loading spinner',如下所示:

.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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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

是否有可能确保伪元素不继承动画.spinner,或者伪元素必须始终采用父元素的含义?

Har*_*rry 13

由于伪元素是父元素的子元素,只要父元素具有动画,它就会继续旋转.即使设置animation: none伪元素也无效.

让它看起来好像孩子没有动画的唯一方法是扭转效果,如下面的代码片段所示.正在做的是将相同的动画添加到伪元素,但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);
  }
}
Run Code Online (Sandbox Code Playgroud)
<div class='spinner'></div>
Run Code Online (Sandbox Code Playgroud)


上述片段使用的默认设置transform-origin50% 50%但如果孩子伪元件具有padding和/或margin随后transform-origin设置具有作相应的调整,以避免从产生颤抖样作用的伪元素.计算逻辑在下面的代码段中提供.

.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);
  }
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

定位所述伪元件(使用top,left,bottom,right)也具有影响动画.它还需要transform-origin按顺序进行修改,以使动画正常工作.下面的代码段中提供了一个示例.

.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);
  }
}
Run Code Online (Sandbox Code Playgroud)
<div class='spinner child-positioned'></div>
<div class='spinner child-positioned-negative'></div>
Run Code Online (Sandbox Code Playgroud)

注意:上述两种解决方案在Chrome,Opera和Safari的最新版本中运行良好,但导致文本在IE 11,Edge和Firefox中呈现出倾斜的外观.Firefox似乎需要一个单独的动画,从旋转(-10度)到旋转(-370度)为FF,而它在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);
  }
}
Run Code Online (Sandbox Code Playgroud)
<div class='spinner'>Loading...</div>
Run Code Online (Sandbox Code Playgroud)