使用CSS将图像的白色背景变为透明

37

我有两张图片,其中一张是小图标,另一张是底图。我的图标有白色背景,当将其放置在底图上时,会出现一个白色方块覆盖在底图上的效果。理想情况下,我不想在另一张图片上显示这个白色背景。有没有CSS属性可以应用于我的图标,使它的白色背景变为透明的?


你可以使用像Photoshop这样的工具将图标的背景变为透明。 - Kedume
你不能用CSS做你想做的事情,你必须使用图像编辑工具,就像之前的评论者所说的那样。 - Marcelo De Polli
5个回答

198

1
@SteffiKeranRaniJ 请查看我下面的回答。 这种技术是魔法般的,需要更多的关注。 - dovidweisz
当我尝试这个时,在某些情况下,图像的父元素也必须明确设置背景颜色。例如,如果 body 的背景是红色,但图像在 div 中,则该 div 也需要明确的红色背景才能使混合模式起作用。 - Oliver
9
这不是你们想要实现的效果,只是非常接近。 " Multiply" 是一种合并模式,其中像素颜色值(背景和图片层)进行反向相乘;因此,白色 * 白色 = 白色,任何颜色 * 白色 = 任何颜色,任何颜色 * 黑色 = 黑色。因此,如果您的图标只有黑色和白色,这种方法将起作用(不适用于反锯齿边缘!),否则它将更改两个图层都具有除黑/白以外的其他颜色的地方的颜色。在常用的合并模式中,没有"白色表示透明"这样的东西。 - dkellner
@dkellner 原则上,如果有翻译是可能的,那么就应该可以与其他元素结合起来,以便专注于白色。 - LTPCGO

23

Opacitator

mix-blend-mode可以在某些浏览器上使用,但我们发现它会在Chrome浏览器中导致性能问题,我不知道为什么

我的团队中的一位设计师提出了这个天才的技巧,它创建了一个图层,该图层基本透明,但是当它铺在白色背景上时,它的颜色将与周围背景的颜色相匹配。

找到这个“神奇”的颜色的方法是通过计算每个颜色轴的变暗程度来确定删除的不透明度量。 公式为 255 - ( 255 - x ) / opacity。问题在于:如果不透明度设置得太低,则公式会给出负数(无法使用)。 如果不透明度太高,则您将在图像的非白色部分获得一些上色。
最初,我们使用电子表格进行计算,并通过手动试错找到那个Goldilox颜色。
一旦我们开始使用Sass,我意识到这可以通过二进制搜索完成。 所以我创建了一个Sass函数来为我们完成这项工作。

请查看此代码片段SassMeister中。在Sass代码的第56行中,将您的背景颜色传递到opacitator函数中,并在一个div(或伪元素)中使用生成的rgba颜色来覆盖图像。

我还创建了一个CodePen实例


这仍然存在一个问题,即它会重新着色图像。假设您有一个白色背景的图像和一个绿色背景的容器。您希望图像中的白色变为透明,以显示为绿色,并使图像的其余部分保持正常。这里是否可能实现? - Douglas Gaskell
@douglas-gaskell 为什么不 fork 这个 CodePen 并自己试一下呢? - dovidweisz
1
非常好用。即使使用 https://github.com/scssphp/scssphp 也没有问题。 - Rauli Rajande
1
这是一些优美的代码。感谢您分享它。 - Danielle

6

由于CSS没有可靠的方法来删除背景,所以分享一下使用JS进行操作的代码片段:

public async removeImageBackground(image) {
  const backgroundColor = { red: 255, green: 255, blue: 255 };
  const threshold = 10;

  const imageElement = new Image();
  imageElement.src = image;
  await new Promise(function(resolve) { imageElement.addEventListener('load', resolve); });

  var canvas = document.createElement('canvas');
  canvas.width = imageElement.naturalWidth;
  canvas.height = imageElement.naturalHeight;

  var ctx = canvas.getContext('2d');
  ctx.drawImage(imageElement, 0, 0);
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  for (var i = 0; i < imageData.data.length; i += 4) {
    const red = imageData.data[i];
    const green = imageData.data[i + 1];
    const blue = imageData.data[i + 2];
    if (Math.abs(red - backgroundColor.red) < threshold &&
      Math.abs(green - backgroundColor.green) < threshold &&
      Math.abs(blue - backgroundColor.blue) < threshold) {
      imageData.data[i + 3] = 0;
    }
  }

  ctx.putImageData(imageData, 0, 0);
  return canvas.toDataURL(`image/png`);
}

哇,不错,这非常令人印象深刻 :D - Dobromir Kirov
目前为止最佳解决方案! - Aurélien B.

2
你可以为你的图片创建一个容器。 然后对于容器的CSS:
overflow:hidden; height: (depends on your image, then make it a smaller px); width:100%;

希望能对你有所帮助。 :)

谢谢,这是最快捷的技巧。你帮我省了好几个小时的工作! - Julien Le Coupanec

2

还没有。但是现在非常接近了。

不过,这个实验性的CSS特性——CSS滤镜——正在客户端做一些很棒的事情。请查看这篇文章。

CSS滤镜


CSS滤镜现在在Firefox中默认开启。 - Anthony M. Powers
1
我该如何使用它来完成所要求的任务? - ADTC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接