标题几乎说明了一切,但这是一个例子。
假设我有一个CSS'loading spinner',如下所示:
gender
我想为此添加一个伪元素 - 例如在.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...'
。
是否可以确保伪元素不会从.spinner
继承动画,或者伪元素总是取得父元素的含义?
答案 0 :(得分:12)
由于伪元素是父元素的子元素,只要父元素具有动画,它就会继续旋转。即使在伪元素上设置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
和/或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);
}
}
<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
以使动画正常工作。下面的代码段中提供了一个示例。
.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似乎需要一个单独的动画,从旋转(-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);
}
}
<div class='spinner'>Loading...</div>
答案 1 :(得分:2)
为了完整地回答@Harry的综合答案,我制作了一个带有微调器下方文本的版本。方法是使用.spinner
作为画布,将实际旋转圈:before
和loading...
放在: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);
}
}
<div class='spinner'></div>