Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
319 views
in Technique[技术] by (71.8m points)

javascript - Image background color bleeding on circular image

I have a circular image (a profile picture). This image may or may not be translucent so I've given it a background color to ensure that it's always visible. The problem I'm having is that the background color is visible even on images that are completely opaque (see figures).

After messing around with borders and padding I found a workaround. I found that adding an invisible border, and then removing it will fix the problem. To deal with images being dynamically added and removed, I do this on a timer (this was easier than injecting some code in all places where images are added to the page). This is what I've done and it seems to work but I don't like it.

setInterval(() => {
  for (const img of document.getElementsByTagName("img")) {
    if (img.style.border.length) {
      img.style.border = "";
    } else {
      img.style.border = "0 solid transparent";
    }
  }
}, 500);

The <img> has the width and height attributes set to 32. It also has a border-radius of 16px and of course, a background-color.

Surely there must be a better way to deal with this than the setInterval above. Changing the border seems to be causing the element to be rendered again (and correctly). Perhaps there's a way to do this more directly?

Since this is a weird rendering issue, I should mention that I'm using Chrome 87.

I found another workaround that's a little bit more efficient. Whenever an image is added to the page, I attached an onload listener that updates the border.

img.onload = () => {
  setTimeout(() => img.style.border = "0 solid transparent", 100);
};

This still feels like an ugly hack. Also, the edge around the image appears briefly before disappearing when the page loads. I'm looking for a better way.

I tried this out in Safari and updating the border doesn't help. It seems like I'll need to think outside the box.


Figure 1

Figure 1 - disgusting


Figure 2

Figure 2 - desired


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Oh neat, what an interesting issue! Unfortunately I've looked and looked and looked and can't seem to see why this is happening. Triggering a reflow of any kind seems to fix it though, so whether you use the border or not should work.

However I think I've found another solution that would work without requiring a reflow, and that's using a radial-gradient background-image instead of a solid background color.

I set up an example pen here: https://codepen.io/xhynk/pen/ZEprxqq (it was easy to increment the ?4 to uncache the image and get it to "act weird" again.

Using this CSS for the background on the image, it seems to prevent the image from being close enough to "bleed" through the edge:

img {
    background-image: radial-gradient(#000 70%, transparent calc(70% + 1px));
}

You could potentially drop the 70% down to 69% if you're still seeing it. I just tried to get it as close to the edge of the container as possible, and the +1px calc smooths it out instead of being jagged.

You can see in the following image, the first avatar has the radial-gradient applied and there's no bleed, and the second has the solid background: black instead which does.

image of bg bleeding through


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...