CSS 滤镜阴影不提供平滑过渡

CSS filter drop-shadow does not provide smooth transition

我有自定义图像帧(在本例中为笔记本电脑),我希望在鼠标悬停时围绕每个图像帧进行阴影过渡。我在这里使用 drop-shadow 过渡,但我无法使用此解决方案实现流畅的跨浏览器行为。

在 Safari 中,转换根本不起作用:

在 chrome 中效果更好但仍然不理想 - 您可以注意到阴影在动画的最后跳跃:

如何修复当前的解决方案,或者任何人都可以建议其他方法来实现相同的解决方案?我只能考虑带有 opacity / scale 动画的额外阴影图像,但这意味着对于我要添加的每一帧 - 我将需要单独的图像作为阴影层,所以我希望社区有更好的解决方案。

UPD: 不要忘记在@Stuart 的出色解决方案之上添加 will-change: opacity 以修复 OSX Safari 渲染问题

.wrapper {
  position: relative;
  transition: filter .5s;
  display: inline-flex;
}

.content {
  top: 7px;
  bottom: 4px;
  left: 13px;
  right: 13px;
  overflow: hidden;
  position: absolute;
  background: #F4F4F5;
  z-index: 0;
}

img {
  position: relative;
  width: 100%;
  height: 100%;
}

svg {
  position: relative;
  z-index: 1;
}

.wrapper:hover {
  filter: drop-shadow(2px 2px 2px #44444444);
}
<div class="wrapper">
  <div class="content">
    <img src="https://picsum.photos/133/96" />
  </div>
  <svg width="161" height="107" viewBox="0 0 161 107" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path fill-rule="evenodd" clip-rule="evenodd" d="M15.9128 0C11.7771 0 8.42442 3.91065 8.42442 8.73469V99.3571H0.936047C0.419082 99.3571 0 99.846 0 100.449V103.724C0 105.534 1.25725 107 2.80814 107H158.192C159.743 107 161 105.534 161 103.724V100.449C161 99.846 160.581 99.3571 160.064 99.3571H152.576V8.73469C152.576 3.91065 149.223 0 145.087 0H15.9128ZM147.895 100.449V8.73469H13.1047V100.449H65.5233C65.5233 101.655 66.3614 102.633 67.3954 102.633H91.7326C92.7665 102.633 93.6047 101.655 93.6047 100.449H147.895ZM79.0959 6.55102C79.8714 6.55102 80.5 5.81778 80.5 4.91327C80.5 4.00875 79.8714 3.27551 79.0959 3.27551C78.3205 3.27551 77.6919 4.00875 77.6919 4.91327C77.6919 5.81778 78.3205 6.55102 79.0959 6.55102Z" fill="white"/>
    <path fill-rule="evenodd" clip-rule="evenodd" d="M9.36047 100.449H0.936047V103.724C0.936047 104.931 1.77421 105.908 2.80814 105.908H158.192C159.226 105.908 160.064 104.931 160.064 103.724V100.449H151.64V8.73469C151.64 4.51366 148.706 1.09184 145.087 1.09184H15.9128C12.294 1.09184 9.36047 4.51366 9.36047 8.73469V100.449ZM8.42442 8.73469C8.42442 3.91065 11.7771 0 15.9128 0H145.087C149.223 0 152.576 3.91065 152.576 8.73469V99.3571H160.064C160.581 99.3571 161 99.846 161 100.449V103.724C161 105.534 159.743 107 158.192 107H2.80814C1.25725 107 0 105.534 0 103.724V100.449C0 99.846 0.419082 99.3571 0.936047 99.3571H8.42442V8.73469ZM80.5 4.91327C80.5 5.81778 79.8714 6.55102 79.0959 6.55102C78.3205 6.55102 77.6919 5.81778 77.6919 4.91327C77.6919 4.00875 78.3205 3.27551 79.0959 3.27551C79.8714 3.27551 80.5 4.00875 80.5 4.91327Z" fill="#E8E8EA"/>
  </svg>
</div>

如果您从具有相同尺寸但只是透明的初始阴影开始,您会获得更平滑的过渡,因为阴影已经存在:

.wrapper {
  position: relative;
  transition: filter .5s;
  display: inline-flex;
  filter: drop-shadow(2px 2px 2px transparent);
}

.content {
  top: 7px;
  bottom: 4px;
  left: 13px;
  right: 13px;
  overflow: hidden;
  position: absolute;
  z-index: 0;
}

img {
  position: relative;
  width: 100%;
  height: 100%;
}

svg {
  position: relative;
  z-index: 1;
}

.wrapper:hover {
  filter: drop-shadow(2px 2px 2px #44444444);
}
<div class="wrapper">
  <div class="content">
    <img src="https://picsum.photos/133/96" />
  </div>
  <svg width="161" height="107" viewBox="0 0 161 107" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path fill-rule="evenodd" clip-rule="evenodd" d="M15.9128 0C11.7771 0 8.42442 3.91065 8.42442 8.73469V99.3571H0.936047C0.419082 99.3571 0 99.846 0 100.449V103.724C0 105.534 1.25725 107 2.80814 107H158.192C159.743 107 161 105.534 161 103.724V100.449C161 99.846 160.581 99.3571 160.064 99.3571H152.576V8.73469C152.576 3.91065 149.223 0 145.087 0H15.9128ZM147.895 100.449V8.73469H13.1047V100.449H65.5233C65.5233 101.655 66.3614 102.633 67.3954 102.633H91.7326C92.7665 102.633 93.6047 101.655 93.6047 100.449H147.895ZM79.0959 6.55102C79.8714 6.55102 80.5 5.81778 80.5 4.91327C80.5 4.00875 79.8714 3.27551 79.0959 3.27551C78.3205 3.27551 77.6919 4.00875 77.6919 4.91327C77.6919 5.81778 78.3205 6.55102 79.0959 6.55102Z" fill="white"/>
    <path fill-rule="evenodd" clip-rule="evenodd" d="M9.36047 100.449H0.936047V103.724C0.936047 104.931 1.77421 105.908 2.80814 105.908H158.192C159.226 105.908 160.064 104.931 160.064 103.724V100.449H151.64V8.73469C151.64 4.51366 148.706 1.09184 145.087 1.09184H15.9128C12.294 1.09184 9.36047 4.51366 9.36047 8.73469V100.449ZM8.42442 8.73469C8.42442 3.91065 11.7771 0 15.9128 0H145.087C149.223 0 152.576 3.91065 152.576 8.73469V99.3571H160.064C160.581 99.3571 161 99.846 161 100.449V103.724C161 105.534 159.743 107 158.192 107H2.80814C1.25725 107 0 105.534 0 103.724V100.449C0 99.846 0.419082 99.3571 0.936047 99.3571H8.42442V8.73469ZM80.5 4.91327C80.5 5.81778 79.8714 6.55102 79.0959 6.55102C78.3205 6.55102 77.6919 5.81778 77.6919 4.91327C77.6919 4.00875 78.3205 3.27551 79.0959 3.27551C79.8714 3.27551 80.5 4.00875 80.5 4.91327Z" fill="#E8E8EA"/>
  </svg>
</div>

根据@Stuart 的回答:

在实际代码中,我不会使用重复的内联 svg,但这里为了简化解决方案,我只是复制粘贴它以创建应用了 drop-shadow 的额外图层,我只会更改 transform/opacity鼠标悬停时的阴影层。

.wrapper {
  position: relative;
  transition: filter .5s;
  display: inline-flex;
}

.content {
  top: 7px;
  bottom: 4px;
  left: 13px;
  right: 13px;
  overflow: hidden;
  position: absolute;
  background: #F4F4F5;
  z-index: 0;
}

img {
  position: relative;
  width: 100%;
  height: 100%;
}

.shadow-holder {
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  position: absolute;
  filter: drop-shadow(2px 2px 2px #44444444);
  opacity: 0;
  z-index: -1;
  transition: opacity .3s;
  transform: translateX(-1px) translateY(-1px);
}

svg {
  position: relative;
  z-index: 1;
}

.wrapper:hover .shadow-holder {
  opacity: 1;
  transform: none;
}
<div class="wrapper">
  <div class="content">
    <img src="https://picsum.photos/133/96" />
  </div>
  <svg width="161" height="107" viewBox="0 0 161 107" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path fill-rule="evenodd" clip-rule="evenodd" d="M15.9128 0C11.7771 0 8.42442 3.91065 8.42442 8.73469V99.3571H0.936047C0.419082 99.3571 0 99.846 0 100.449V103.724C0 105.534 1.25725 107 2.80814 107H158.192C159.743 107 161 105.534 161 103.724V100.449C161 99.846 160.581 99.3571 160.064 99.3571H152.576V8.73469C152.576 3.91065 149.223 0 145.087 0H15.9128ZM147.895 100.449V8.73469H13.1047V100.449H65.5233C65.5233 101.655 66.3614 102.633 67.3954 102.633H91.7326C92.7665 102.633 93.6047 101.655 93.6047 100.449H147.895ZM79.0959 6.55102C79.8714 6.55102 80.5 5.81778 80.5 4.91327C80.5 4.00875 79.8714 3.27551 79.0959 3.27551C78.3205 3.27551 77.6919 4.00875 77.6919 4.91327C77.6919 5.81778 78.3205 6.55102 79.0959 6.55102Z" fill="white"/>
    <path fill-rule="evenodd" clip-rule="evenodd" d="M9.36047 100.449H0.936047V103.724C0.936047 104.931 1.77421 105.908 2.80814 105.908H158.192C159.226 105.908 160.064 104.931 160.064 103.724V100.449H151.64V8.73469C151.64 4.51366 148.706 1.09184 145.087 1.09184H15.9128C12.294 1.09184 9.36047 4.51366 9.36047 8.73469V100.449ZM8.42442 8.73469C8.42442 3.91065 11.7771 0 15.9128 0H145.087C149.223 0 152.576 3.91065 152.576 8.73469V99.3571H160.064C160.581 99.3571 161 99.846 161 100.449V103.724C161 105.534 159.743 107 158.192 107H2.80814C1.25725 107 0 105.534 0 103.724V100.449C0 99.846 0.419082 99.3571 0.936047 99.3571H8.42442V8.73469ZM80.5 4.91327C80.5 5.81778 79.8714 6.55102 79.0959 6.55102C78.3205 6.55102 77.6919 5.81778 77.6919 4.91327C77.6919 4.00875 78.3205 3.27551 79.0959 3.27551C79.8714 3.27551 80.5 4.00875 80.5 4.91327Z" fill="#E8E8EA"/>
  </svg>
  <svg class="shadow-holder" width="161" height="107" viewBox="0 0 161 107" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path fill-rule="evenodd" clip-rule="evenodd" d="M15.9128 0C11.7771 0 8.42442 3.91065 8.42442 8.73469V99.3571H0.936047C0.419082 99.3571 0 99.846 0 100.449V103.724C0 105.534 1.25725 107 2.80814 107H158.192C159.743 107 161 105.534 161 103.724V100.449C161 99.846 160.581 99.3571 160.064 99.3571H152.576V8.73469C152.576 3.91065 149.223 0 145.087 0H15.9128ZM147.895 100.449V8.73469H13.1047V100.449H65.5233C65.5233 101.655 66.3614 102.633 67.3954 102.633H91.7326C92.7665 102.633 93.6047 101.655 93.6047 100.449H147.895ZM79.0959 6.55102C79.8714 6.55102 80.5 5.81778 80.5 4.91327C80.5 4.00875 79.8714 3.27551 79.0959 3.27551C78.3205 3.27551 77.6919 4.00875 77.6919 4.91327C77.6919 5.81778 78.3205 6.55102 79.0959 6.55102Z" fill="white"/>
    <path fill-rule="evenodd" clip-rule="evenodd" d="M9.36047 100.449H0.936047V103.724C0.936047 104.931 1.77421 105.908 2.80814 105.908H158.192C159.226 105.908 160.064 104.931 160.064 103.724V100.449H151.64V8.73469C151.64 4.51366 148.706 1.09184 145.087 1.09184H15.9128C12.294 1.09184 9.36047 4.51366 9.36047 8.73469V100.449ZM8.42442 8.73469C8.42442 3.91065 11.7771 0 15.9128 0H145.087C149.223 0 152.576 3.91065 152.576 8.73469V99.3571H160.064C160.581 99.3571 161 99.846 161 100.449V103.724C161 105.534 159.743 107 158.192 107H2.80814C1.25725 107 0 105.534 0 103.724V100.449C0 99.846 0.419082 99.3571 0.936047 99.3571H8.42442V8.73469ZM80.5 4.91327C80.5 5.81778 79.8714 6.55102 79.0959 6.55102C78.3205 6.55102 77.6919 5.81778 77.6919 4.91327C77.6919 4.00875 78.3205 3.27551 79.0959 3.27551C79.8714 3.27551 80.5 4.00875 80.5 4.91327Z" fill="#E8E8EA"/>
  </svg>
</div>