如果 div:before 浮动 (WebKit),CSS3 动画不起作用
CSS3 animation doesn't work if div:before is floating (WebKit)
我希望我的文本仅使用 CSS3 闪烁。它工作正常。但是,如果我将 float:left
添加到 div 的 :before
选择器,它会阻止动画在 WebKit (Safari/Chrome) 上运行。
为了演示,在 WebKit 上打开 JSFiddle,删除 float:left
以查看它是否正常工作。
CSS:
.blink_me:before {
content: "Blink";
}
.blink_me {
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% { opacity: 0.0; }
}
HTML:
<span class="blink_me"> </span>
如何让它与选择器上的浮动一起使用?
赏金信息:只是奖励一个肯定值得更多赞成票的现有答案。
原因:
这肯定是因为Webkit 中的层创建和加速渲染过程。在 Dev Tools 中启用 "Show Paint Rects" 和 "Show Composited Layer Borders" 选项后,查看此答案中的所有演示。
当任何一个演示是 运行 时,您会看到一些绿色和橙色的框。绿色框是绘制矩形,而橙色框是渲染引擎为加速渲染而创建的合成层。在渲染过程中,Webkit(和 Blink)并不总是重新绘制整个页面。只有受影响的页面区域(层)会被重新绘制(为了性能)。
带浮动:
在此代码段中,您会看到渲染引擎创建一个绘制矩形、页面的合成层和另一个绘制矩形、[=31=] 元素的合成层("Some Content").由于 span
是一个 inline
元素,它不会生成包含其后代框和生成内容的 principal block-level box。这(根据我的理解)使伪元素相对于根元素浮动。这也意味着伪元素在屏幕上的位置不依赖于父 span
元素(事实上,如果你给 span
一个负边距,你会注意到内容重叠,而如果 display: block
设置为 span
,则负边距会将伪元素的内容也移动到左侧)。由于浮动元素的状态不影响跨度,并且它也没有自己的合成层,因此动画不会改变其不透明度。
.blink_me:before {
content: "Blink";
float: left;
}
.blink_me {
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me">Some content</span>
没有浮动:
这里引擎也创建了两个层 + 两个绘制矩形但是因为没有浮动,伪元素也是 inline
并且是父元素 span
的一部分(你会请参阅一个包含 "Blink" 和 "Some content" 的方框)。现在由于伪元素的内容也是父层的一部分,父层的动画也会影响伪元素的内容。
.blink_me:before {
content: "Blink";
}
.blink_me {
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me">Some content</span>
解决方案:
执行以下任何一项操作都会导致伪元素的内容被视为父元素层的一部分,因此父元素上的动画也会影响子元素。当应用这些设置中的任何一个时,您会再次注意到覆盖 span 元素内容和伪元素内容的橙色边框。
在伪元素上设置任何position
(相对或绝对甚至固定)。
.blink_me:before {
content: "Blink";
float: left;
position: relative;
}
.blink_me {
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me">Some content</span>
在伪元素上设置除 1 以外的 opacity
(如 0.99 等)。
.blink_me:before {
content: "Blink";
float: left;
opacity: 0.99;
}
.blink_me {
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me">Some content</span>
在伪元素上设置transform: translateZ(0px);
。
.blink_me:before {
content: "Blink";
float: left;
transform: translateZ(0px);
}
.blink_me {
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me">Some content</span>
或者,另一种解决方案是直接在伪元素上设置动画,因为它会获得自己的合成层,并且只有该层受到影响。
.blink_me:before {
content: "Blink";
float: left;
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me"> </span>
另一个有效的选项是将 display
设置为 inline-block
或 block
到父级 span
。这也使伪元素成为父元素合成层的一部分,因此它也受到动画的影响。
.blink_me:before {
content: "Blink";
float: left;
}
.blink_me {
display: inline-block;
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me"> </span>
总结
在参考资料下提供的第二个 link 中,您会看到渲染过程在 WebKit(和 Blink)中是如何工作的,从节点到渲染对象到渲染层到合成图层。
下面总结了这些如何应用于此答案中的所有演示,以及为什么每个演示都按原样工作。
伪元素上没有float时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | No | N/A
此处 span
动画一开始就获得一个渲染层,因为它是半透明的(由于不透明),并且它获得一个合成层,因为它有不透明动画。 pseudo 没有自己的渲染层,因为它不满足任何要求的标准,因此也没有获得合成层。它成为第一个祖先的渲染+合成层的一部分。在合成过程中,pseudo的内容也会受到影响,因为它也是图层的一部分。
伪元素上有float时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | No | N/A
与之前相同,但由于有一个浮点数并且它不是 span
的一部分,因此伪对象不是其合成层的一部分,因此在合成操作期间不会被修改。
伪元素定位时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | Yes | No
当 psuedo 被定位时,它会获得自己的渲染层(因为它符合条件)但不会获得合成层,因为它不符合所需的条件。此外,它的定位意味着它在屏幕上的位置会受到跨度上任何变换的影响。看起来这使得伪元素也成为跨度合成层的一部分,因此作为合成操作的一部分被修改。
当伪元素的不透明度小于1时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | Yes | No
与上一个案例类似。这里的不透明度小于 1 的 pseudo 意味着当它下面的层发生变化时它需要改变(否则,透明度会被破坏)。因此,这似乎被移到了合成层,因此在合成过程中被修改了。
当伪元素有变换时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | Yes | Yes
这里,pseudo 也有自己的合成层,因为它上面有 3D 变换,并且因为它是 span
的子层,所以它的层在 span 的层之上。这意味着在合成过程中,span 和伪元素的图层都会被修改,因此动画也会影响这里的伪元素。
伪元素直接动画时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | No | N/A
:before | Yes | Yes | Yes | Yes
此处,span
没有渲染层或合成层,因为不透明动画位于伪元素上。由于 pseudo 有自己的合成层,因此在合成过程中它也会受到影响。
当 span 显示为块或行内块时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | No | N/A
这与伪元素浮动的情况非常相似,但由于这里的 span 是块级元素,它会为其后代和生成的内容生成主要的块级框。因此,伪对象成为跨度合成层的一部分,因此在合成过程中会受到影响。
Note: The whole rendering process is very complex as you could see from the reference links and I've tried my best to explain the process. There are chances that I could have some of the intricate details wrong but on the overall you'd find that the explanation tallies with the Dev tools output.
参考文献:
您可以通过参考以下 link 找到有关如何启用 "Show Paint Rects"、"Show Composited Layer Borders" 选项以及加速渲染过程如何工作的更多信息:
我希望我的文本仅使用 CSS3 闪烁。它工作正常。但是,如果我将 float:left
添加到 div 的 :before
选择器,它会阻止动画在 WebKit (Safari/Chrome) 上运行。
为了演示,在 WebKit 上打开 JSFiddle,删除 float:left
以查看它是否正常工作。
CSS:
.blink_me:before {
content: "Blink";
}
.blink_me {
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% { opacity: 0.0; }
}
HTML:
<span class="blink_me"> </span>
如何让它与选择器上的浮动一起使用?
赏金信息:只是奖励一个肯定值得更多赞成票的现有答案。
原因:
这肯定是因为Webkit 中的层创建和加速渲染过程。在 Dev Tools 中启用 "Show Paint Rects" 和 "Show Composited Layer Borders" 选项后,查看此答案中的所有演示。
当任何一个演示是 运行 时,您会看到一些绿色和橙色的框。绿色框是绘制矩形,而橙色框是渲染引擎为加速渲染而创建的合成层。在渲染过程中,Webkit(和 Blink)并不总是重新绘制整个页面。只有受影响的页面区域(层)会被重新绘制(为了性能)。
带浮动:
在此代码段中,您会看到渲染引擎创建一个绘制矩形、页面的合成层和另一个绘制矩形、[=31=] 元素的合成层("Some Content").由于 span
是一个 inline
元素,它不会生成包含其后代框和生成内容的 principal block-level box。这(根据我的理解)使伪元素相对于根元素浮动。这也意味着伪元素在屏幕上的位置不依赖于父 span
元素(事实上,如果你给 span
一个负边距,你会注意到内容重叠,而如果 display: block
设置为 span
,则负边距会将伪元素的内容也移动到左侧)。由于浮动元素的状态不影响跨度,并且它也没有自己的合成层,因此动画不会改变其不透明度。
.blink_me:before {
content: "Blink";
float: left;
}
.blink_me {
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me">Some content</span>
没有浮动:
这里引擎也创建了两个层 + 两个绘制矩形但是因为没有浮动,伪元素也是 inline
并且是父元素 span
的一部分(你会请参阅一个包含 "Blink" 和 "Some content" 的方框)。现在由于伪元素的内容也是父层的一部分,父层的动画也会影响伪元素的内容。
.blink_me:before {
content: "Blink";
}
.blink_me {
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me">Some content</span>
解决方案:
执行以下任何一项操作都会导致伪元素的内容被视为父元素层的一部分,因此父元素上的动画也会影响子元素。当应用这些设置中的任何一个时,您会再次注意到覆盖 span 元素内容和伪元素内容的橙色边框。
在伪元素上设置任何
position
(相对或绝对甚至固定)。.blink_me:before { content: "Blink"; float: left; position: relative; } .blink_me { -webkit-animation: blinker 1.5s linear infinite; -moz-animation: blinker 1.5s linear infinite; -o-animation: blinker 1.5s linear infinite; animation: blinker 1.5s linear infinite; } @keyframes blinker { 50% { opacity: 0.0; } }
<span class="blink_me">Some content</span>
在伪元素上设置除 1 以外的
opacity
(如 0.99 等)。.blink_me:before { content: "Blink"; float: left; opacity: 0.99; } .blink_me { -webkit-animation: blinker 1.5s linear infinite; -moz-animation: blinker 1.5s linear infinite; -o-animation: blinker 1.5s linear infinite; animation: blinker 1.5s linear infinite; } @keyframes blinker { 50% { opacity: 0.0; } }
<span class="blink_me">Some content</span>
在伪元素上设置
transform: translateZ(0px);
。.blink_me:before { content: "Blink"; float: left; transform: translateZ(0px); } .blink_me { -webkit-animation: blinker 1.5s linear infinite; -moz-animation: blinker 1.5s linear infinite; -o-animation: blinker 1.5s linear infinite; animation: blinker 1.5s linear infinite; } @keyframes blinker { 50% { opacity: 0.0; } }
<span class="blink_me">Some content</span>
或者,另一种解决方案是直接在伪元素上设置动画,因为它会获得自己的合成层,并且只有该层受到影响。
.blink_me:before {
content: "Blink";
float: left;
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me"> </span>
另一个有效的选项是将 display
设置为 inline-block
或 block
到父级 span
。这也使伪元素成为父元素合成层的一部分,因此它也受到动画的影响。
.blink_me:before {
content: "Blink";
float: left;
}
.blink_me {
display: inline-block;
-webkit-animation: blinker 1.5s linear infinite;
-moz-animation: blinker 1.5s linear infinite;
-o-animation: blinker 1.5s linear infinite;
animation: blinker 1.5s linear infinite;
}
@keyframes blinker {
50% {
opacity: 0.0;
}
}
<span class="blink_me"> </span>
总结
在参考资料下提供的第二个 link 中,您会看到渲染过程在 WebKit(和 Blink)中是如何工作的,从节点到渲染对象到渲染层到合成图层。
下面总结了这些如何应用于此答案中的所有演示,以及为什么每个演示都按原样工作。
伪元素上没有float时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | No | N/A
此处 span
动画一开始就获得一个渲染层,因为它是半透明的(由于不透明),并且它获得一个合成层,因为它有不透明动画。 pseudo 没有自己的渲染层,因为它不满足任何要求的标准,因此也没有获得合成层。它成为第一个祖先的渲染+合成层的一部分。在合成过程中,pseudo的内容也会受到影响,因为它也是图层的一部分。
伪元素上有float时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | No | N/A
与之前相同,但由于有一个浮点数并且它不是 span
的一部分,因此伪对象不是其合成层的一部分,因此在合成操作期间不会被修改。
伪元素定位时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | Yes | No
当 psuedo 被定位时,它会获得自己的渲染层(因为它符合条件)但不会获得合成层,因为它不符合所需的条件。此外,它的定位意味着它在屏幕上的位置会受到跨度上任何变换的影响。看起来这使得伪元素也成为跨度合成层的一部分,因此作为合成操作的一部分被修改。
当伪元素的不透明度小于1时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | Yes | No
与上一个案例类似。这里的不透明度小于 1 的 pseudo 意味着当它下面的层发生变化时它需要改变(否则,透明度会被破坏)。因此,这似乎被移到了合成层,因此在合成过程中被修改了。
当伪元素有变换时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | Yes | Yes
这里,pseudo 也有自己的合成层,因为它上面有 3D 变换,并且因为它是 span
的子层,所以它的层在 span 的层之上。这意味着在合成过程中,span 和伪元素的图层都会被修改,因此动画也会影响这里的伪元素。
伪元素直接动画时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | No | N/A
:before | Yes | Yes | Yes | Yes
此处,span
没有渲染层或合成层,因为不透明动画位于伪元素上。由于 pseudo 有自己的合成层,因此在合成过程中它也会受到影响。
当 span 显示为块或行内块时:
Element | Node | Render Object | Render Layer | Compositing Layer
-----------------------------------------------------------------------------------------
Root | Yes | Yes | Yes | Yes (Descendant is a compositing layer)
span | Yes | Yes | Yes | Yes
:before | Yes | Yes | No | N/A
这与伪元素浮动的情况非常相似,但由于这里的 span 是块级元素,它会为其后代和生成的内容生成主要的块级框。因此,伪对象成为跨度合成层的一部分,因此在合成过程中会受到影响。
Note: The whole rendering process is very complex as you could see from the reference links and I've tried my best to explain the process. There are chances that I could have some of the intricate details wrong but on the overall you'd find that the explanation tallies with the Dev tools output.
参考文献:
您可以通过参考以下 link 找到有关如何启用 "Show Paint Rects"、"Show Composited Layer Borders" 选项以及加速渲染过程如何工作的更多信息: