如果 div :before is floating (WebKit),CSS3 动画不起作用

标签 css webkit css-animations

我希望我的文本仅使用 CSS3 闪烁。它工作正常。但是,如果我添加 float:left到 div 的 :before选择器,它会阻止动画在 WebKit (Safari/Chrome) 上工作。

如需演示,请打开 JSFiddle在 WebKit 上,删除 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)并不总是重新绘制整个页面。只有页面的受影响区域(层)会重新绘制(为了性能)。

带 float :

在这个片段中,你会看到渲染引擎创建了一个绘制矩形,一个页面的合成层和一个更多的绘制矩形,合成层 span元素(“某些内容”)。自 spaninline元素,它不会生成 principal block-level box包含其后代的盒子和生成的内容。这(根据我的理解)使伪元素相对于根元素 float 。这也意味着伪元素在屏幕上的位置不依赖于父元素 span元素(事实上,如果你给 span 一个负边距,你会注意到内容重叠,而如果 display: block 设置为 span 一个负边距也会将伪元素的内容向左移动)。由于 float 元素的状态不会影响跨度,并且由于它也没有自己的合成层,因此动画不会改变其不透明度。

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


无 float :

这里引擎也创建了两层 + 两个绘制矩形,但由于没有 float ,伪元素也是 inline并且是父级 span 的一部分(您会看到一个包含“闪烁”和“某些内容”的框)。现在,由于伪元素的内容也是父层的一部分,父元素上的动画也会影响伪元素的内容。

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

  • 设置 opacity除了伪元素上的 1(如 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>


    另一个有效的选项是设置 displayinline-blockblock给 parent 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>



    概括

    在引用下提供的第二个链接中,您将看到渲染过程如何在 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动画一开始就得到一个渲染层,因为它是半透明的(由于不透明),它得到一个合成层,因为它有不透明动画。伪代码没有自己的渲染层,因为它不满足任何要求的标准,因此也没有合成层。它成为第一个祖先的渲染+合成层的一部分。在合成过程中,伪的内容也会受到影响,因为它也是图层的一部分。

    当伪元素有 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
    

    当伪被定位时,它会获得自己的渲染层(因为它符合标准)但不会获得合成层,因为它不符合所需的标准。此外,它的定位意味着它在屏幕上的位置受跨度上的任何变换的影响。看起来这使得伪元素也成为跨度合成层的一部分,因此被修改为合成操作的一部分。

    当伪元素的不透明度小于 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 的伪指令意味着它需要在其下方的图层发生变化时进行更改(否则会破坏透明度)。正因为如此,这似乎被移动到合成层,因此在合成过程中被修改。

    当伪元素有变换时:

    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 的 child 。 ,其层位于跨度层之上。这意味着在合成期间,跨度和伪元素的图层都被修改,因此动画也会影响这里的伪元素。

    当伪元素直接动画时:

    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 有自己的合成层,所以它在合成过程中也会受到影响。

    当跨度显示为块或内联块时:

    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
    

    这与伪元素 float 的情况非常相似,但由于这里的跨度是块级元素,它为其后代和生成的内容生成主要块级框。因此,伪代码成为跨度合成层的一部分,因此在合成过程中会受到影响。

    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.



    引用:

    您可以通过引用以下链接找到有关如何启用“显示绘制矩形”、“显示合成图层边框”选项以及加速渲染过程如何工作的更多信息:
  • HTML5 Rocks - Accelerated Rendering in Chrome
  • GPU Accelerated Compositing in Chrome .
  • 关于如果 div :before is floating (WebKit),CSS3 动画不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36204090/

    相关文章:

    javascript - 如何在 Bootstrap 网站中添加 Logo /客户端 slider

    javascript - 覆盖 <a> 标签的灯箱处理

    css - 多个 webkit 动画

    css - 如何在使用 CSS 完成悬停后淡出

    css - 如何去除过渡过程中出现的小 Angular 点?

    c# - Windows 上基于 Gtk 的 Mono.WebBrowser

    iphone - CSS 更改似乎没有显示在 iPhone 浏览器 (Mobile Webkit/Safari) 中

    css - 将 css 动画与变换相结合

    jquery - 如何在 URL 更改时为 div 赋予 ontouch 效果

    javascript - 将 svg 附加到背景图像中