【问题标题】:CSS animation, only render overlay on specific elements [duplicate]CSS动画,仅在特定元素上渲染覆盖[重复]
【发布时间】:2019-06-05 09:19:02
【问题描述】:

我已经制作了这个加载占位符 css 动画。在白色背景上它看起来是正确的,因为动画/移动渐变是白色的,不透明度为 20%。

但是,有时占位符将位于不同颜色的背景上,并且移动部分也会在背景上变得可见,而不仅仅是在颜色变暗的情况下(这是不希望的)。请看下面的sn-p:

.ph-item {
  position: relative;
  margin-bottom: 10px;
  overflow: hidden;
  border-radius: 2px;
}

.ph-item,
.ph-item *,
.ph-item ::after,
.ph-item ::before {
  box-sizing: border-box;
}

.ph-item::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 50%;
  z-index: 1;
  width: 500%;
  margin-left: -250%;
  animation: phAnimation 0.8s linear infinite;
  background: linear-gradient(to right, rgba(255, 255, 255, 0) 46%, rgba(255, 255, 255, 0.35) 50%, rgba(255, 255, 255, 0) 54%) 50% 50%;
}

.ph-item > * {
  padding-right: 10px;
}

.ph-row {
  margin-bottom: 5px;
}

.ph-row div {
  border-radius: 3px;
  height: 10px;
  background-color: rgba(0, 0, 0, 0.2);
}

.ph-row .standard,
.ph-row.big div {
  height: 20px;
  margin-right: 10px;
}


.ph-float-right {
  float: right;
  padding-left: 10px;
  margin-right: auto;
}

.ph-col-2 {
  width: 16.66667%;
  display: inline-block;
}

.ph-col-4 {
  width: 33.33333%;
  display: inline-block;
}

.ph-col-6 {
  width: 50%;
  display: inline-block;
}

.ph-col-8 {
  width: 66.66667%;
  display: inline-block;
}

.ph-col-10 {
  width: 83.33333%;
  display: inline-block;
}

.ph-col-12 {
  width: 100%;
  display: inline-block;
}

.ph-avatar {
  position: relative;
  width: 100%;
  min-width: 50px;
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 50%;
  overflow: hidden;
}

.ph-avatar::before {
  content: "";
  display: block;
  padding-top: 100%;
}

@keyframes phAnimation {
  0% {
    transform: translate3d(-30%, 0, 0);
  }

  100% {
    transform: translate3d(30%, 0, 0);
  }
}
<div style="width: 500px; height: 50px; background-color: darkblue; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>
<div style="width: 500px; height: 50px; background-color: white; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>

我的问题是,是否有可能以某种方式掩盖动画,使其仅在黑暗部分(ph-avatarph-col-xx)上呈现?

这是如何实现的?

【问题讨论】:

  • 效果相似但思路不同:stackoverflow.com/a/55710038/8620333
  • @TemaniAfif 对我来说似乎是重复的,即使最初的问题不是同一个问题。最终的结果需要相同的方法才能完全轻松地工作。

标签: html css


【解决方案1】:

edit 这其实是Background animation performance的复制品

另一种方法可以将 after 伪与 background-position 的线性梯度重置一起使用。为了让每个伪元素都具有连贯的渐变片段,background-attachment 会将它们放在一起。 background-size 也会有所帮助。

以下想法的演示。 CSS 注释了更新或修改的地方

.ph-item {
  position: relative;
  margin-bottom: 10px;
  overflow: hidden;
  border-radius: 2px;
}

.ph-item,
.ph-item *,
.ph-item ::after,
.ph-item ::before {
  box-sizing: border-box;
}
   /* selector removed 

.ph-item::before 

       and replaced by : */
.ph-avatar::after,
.ph-row .standard::after,
.ph-row .ph-col-10::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 50%;
  z-index: 1;
  width: 500%;
  margin-left: -250%;
  animation: phAnimation 2s linear infinite;/* duration to set to your needs */
  background: linear-gradient(
      to right,
      rgba(255, 255, 255, 0) 46%,
      rgba(255, 255, 255, 0.35) 50%,
      rgba(255, 255, 255, 0) 54%
    )
    50% 50% 
    rgba(0, 0, 0, 0.2);/* move here & added */
  background-attachment: fixed;/*  added */
  background-size: 1000px auto;/*  added */
}

.ph-item > * {
  padding-right: 10px;
}

.ph-row {
  margin-bottom: 5px;
}

.ph-row div {
  border-radius: 3px;
  height: 10px;
 /*background-color: rgba(0, 0, 0, 0.2); or move animation here from pseudo*/
}

.ph-row .standard,
.ph-row.big div {
  height: 20px;
  margin-right: 10px;
}

.ph-float-right {
  float: right;
  padding-left: 10px;
  margin-right: auto;
}

.ph-col-2 {
  width: 16.66667%;
  display: inline-block;
}

.ph-col-4 {
  width: 33.33333%;
  display: inline-block;
}

.ph-col-6 {
  width: 50%;
  display: inline-block;
  position: relative;/*  added */
  overflow: hidden;/*  added */
}

.ph-col-8 {
  width: 66.66667%;
  display: inline-block;
}

.ph-col-10 {
  width: 83.33333%;
  display: inline-block;
  position: relative;/*  added */
  overflow: hidden;/*  added */
}

.ph-col-12 {
  width: 100%;
  display: inline-block;
}

.ph-avatar {
  position: relative;
  width: 100%;
  min-width: 50px;
  border-radius: 50%;
  overflow: hidden;
}

.ph-avatar::before {
  content: "";
  display: block;
  padding-top: 100%;
}

@keyframes phAnimation {
  0% {
    background-position: -1000px 0;/*  modified */
  }

  100% {
    background-position: 1000px 0;/*  modified */
  }
}
<div style="width: 500px; height: 50px; background-color: darkblue; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>
<div style="width: 500px; height: 50px; background-color: white; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>
<div style="width: 500px; height: 50px; background-color: tomato; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>
<div style="width: 500px; height: 50px; background-color: gold; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>
<div style="width: 500px; height: 50px; background-color: purple; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>
<div style="width: 500px; height: 50px; background-color: turquoise; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>
<div style="width: 500px; height: 50px; background-color: gray; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>
<div style="width: 500px; height: 50px; background-color: teal; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard"></div>
        <div class="ph-col-10"></div>
      </div>
    </div>
  </div>
</div>

注意,背景动画可以直接在元素内部设置,伪不需要,除非它们有其他用途。可能的选项https://codepen.io/gc-nomade/pen/byJOJa

【讨论】:

  • 嘿,非常感谢。但是,我不明白这两个问题是如何相关的。我要求使用 css 获得视觉结果,另一个问题是关于产品的性能,尽管它与我试图通过我的结果实现的非常相似。我认为这个解决方案非常顺利,我不担心它的性能,因为我只会展示一个实例,而且只会在很短的时间内展示。非常感谢:)
  • @RasmusPuls 它只与使用的方法有关(主要是背景附件),性能是额外的,也很高兴知道;)操作员也考虑过变换,但没有通过这个想法。他也认为 渐变应该与屏幕相关,而不是与容器相关,这将我们带到这里 ;)
【解决方案2】:

也许一种选择是遮罩两个 svg 图像并为遮罩的属性设置动画。我个人对这种技术并不是很熟悉,但也许这会有所帮助:

https://tympanus.net/codrops/css_reference/mask-composite/

但是,如果您想在 html 中执行此操作(我个人也更喜欢),您可以通过一些技巧来实现该效果:

.ph-item {
  position: relative;
  margin-bottom: 10px;
  overflow: hidden;
  border-radius: 2px;
}

.ph-item,
.ph-item *,
.ph-item ::after,
.ph-item ::before {
  box-sizing: border-box;
}

.highlighted {
  position: relative;
  overflow: hidden;
}

.highlighted::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 1;
  width: 100px;
  animation: 1s linear infinite;
  animation-name: phAnimation;
  background: red;
/*   background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.35) 50%, rgba(255, 255, 255, 0) 100%) 50% 50%; */
}

.ph-avatar.highlighted::before {
  animation-name: phAnimationAvatar;
}

.ph-item > * {
  padding-right: 10px;
}

.ph-row {
  margin-bottom: 5px;
}

.ph-row div {
  border-radius: 3px;
  height: 10px;
  background-color: rgba(0, 0, 0, 0.2);
}

.ph-row .standard,
.ph-row.big div {
  height: 20px;
  margin-right: 10px;
}


.ph-float-right {
  float: right;
  padding-left: 10px;
  margin-right: auto;
}

.ph-col-2 {
  width: 16.66667%;
  display: inline-block;
}

.ph-col-4 {
  width: 33.33333%;
  display: inline-block;
}

.ph-col-6 {
  width: 50%;
  display: inline-block;
}

.ph-col-8 {
  width: 66.66667%;
  display: inline-block;
}

.ph-col-10 {
  width: 83.33333%;
  display: inline-block;
}

.ph-col-12 {
  width: 100%;
  display: inline-block;
}

.ph-avatar {
  position: relative;
  width: 100%;
  min-width: 50px;
  height: 50px;
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 50%;
  overflow: hidden;
}


@keyframes phAnimationAvatar {
  0% {
    transform: translate3d(-100px, 0, 0);
  }
  
  10% {
    transform: translate3d(-50px, 0, 0);
  }
  
  20% {
    transform: translate3d(0px, 0, 0);
  }
  
  30% {
    transform: translate3d(50px, 0, 0);
  }

  100% {
    transform: translate3d(100px, 0, 0);
  }
}

@keyframes phAnimation {
  0% {
    transform: translate3d(-100px, 0, 0);
  }
  
  11% {
    transform: translate3d(-100px, 0, 0);
  }

  50% {
    transform: translate3d(85px, 0, 0);
  }
  
  100% {
    transform: translate3d(335px, 0, 0);
  }
}
<div style="width: 500px; height: 50px; background-color: darkblue; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar highlighted"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard highlighted"></div>
        <div class="ph-col-10 highlighted"></div>
      </div>
    </div>
  </div>
</div>
<div style="width: 500px; height: 50px; background-color: white; padding: 20px;">
  <div class="ph-item" style="max-width: 360px;">
    <div class="ph-col-2">
      <div class="ph-avatar highlighted"></div>
    </div>
    <div class="ph-col-10 ph-float-right">
      <div class="ph-row">
        <div class="ph-col-6 standard highlighted"></div>
        <div class="ph-col-10 highlighted"></div>
      </div>
    </div>
  </div>
</div>

缺点是您需要针对不同的占位符重新校准动画,但它仍然比为每个占位符元素使用静态 svg 更好。

编辑:只是提醒一下,虽然 chrome 和 firefox 可以正常工作,但 safari 的渲染方式似乎存在问题。

【讨论】:

  • 是的,safari 似乎忽略了before 元素上的边框半径/圆形形状。除此之外,它看起来如所愿。唯一的缺点是它不是很通用。如果我需要在其他地方再放置一个灰色 div,那也需要它自己独特的动画来对齐滚动渐变元素的流动。这就是为什么我希望某种遮罩属性会导致像素仅在具有此属性的元素上呈现,而动画在父级中运行。我是 css 的新手,但在大多数图像编辑软件(如 Photoshop)中这很容易。
  • 是的,我知道你的意思。我确实测试了在 HTML 代码中渲染一个蒙版的 SVG(以便以后可以轻松地对其组件进行动画/修改),但浏览器似乎并没有接受该蒙版。不幸的是,css mask 属性似乎也只适用于外部图像,所以我不知道你是否可以在其中添加 in-html svgs。
  • 有趣。我想知道是否所有这些占位符(许多网站都使用它们,facebook 等)在不同的背景颜色下看起来都很傻,或者他们是否设法以某种方式解决了这个问题。也许另一种方法是更改​​覆盖元素的颜色以匹配背景颜色,而不是强制使用白色半透明覆盖。
猜你喜欢
  • 2019-09-25
  • 2016-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-13
  • 2015-06-17
  • 2016-03-13
  • 1970-01-01
相关资源
最近更新 更多