一尘不染

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

css

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

假设我有一个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);
  }
}

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

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


阅读 299

收藏
2020-05-16

共1个答案

一尘不染

由于伪元素是父元素的子元素,因此只要父元素具有动画,它将继续旋转。即使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);

  }

}


<div class='spinner'></div>

上面的代码段使用的默认设置transform-origin是,50% 50%但如果子伪元素具有padding和/或margintransform- 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);

  }

}


<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>

定位所述伪元件(使用topleftbottomright)也具有影响动画。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);

  }

}


<div class='spinner child-positioned'></div>

<div class='spinner child-positioned-negative'></div>

注意: 以上两种解决方案在最新版本的Chrome,Opera和Safari中都可以正常工作,但会导致文本在IE
11,Edge和Firefox中显示倾斜。Firefox似乎需要一个单独的动画,该动画从FF的rotate(-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);

  }

}


<div class='spinner'>Loading...</div>
2020-05-16