Bright "border", showing due to the background color on the wrapping element with a boundary radius: 50%;

As I tried to make an animated figure (transitions on hover), I found out that the background of my <figure> displayed near the edges when I apply a border radius: 50% to it, even if my image should occupy all the free space.

For a quick demo that illustrates the problem, check out http://codepen.io/anon/pen/KwMMKz

HTML

 <figure> <img src="http://placehold.it/400x400" alt> <figcaption>Demo</figcaption> </figure> 

CSS

 figure { background-color: red; width: 400px; height: 400px; border-radius: 50%; overflow: hidden; position: relative; /* For caption */ } img { border-radius: 50%; /* Forced on image for smooth transition */ width: 100%; transition: opacity 1s ease-out; } figcaption { position: absolute; top: 100%; left: 0; width: 100%; color: hotpink; text-align: center; transition: top 1s ease-out; } figure:hover img { opacity: 0; } figure:hover figcaption { top: 50%; } 

Pay attention . I know that placing the background color in the picture: hover is a workaround, but I'm more interested in the reason for this “jagged edge” to appear.

I assume this is due to the AA rendering (or something related) with the browser and that it treats the <figure> element differently than a multimedia element such as <img> , but I cannot find any evidence of this online. Is this a bug, is it a "feature", or can I fix it?

Finally, I also know that I could use transform: translateY(); here for animation, but this is not part of my question, so please do not provide it as an answer.

UPDATE 17/12 14:03

It seems that this question is not exclusive to the border radius: 50%. A problem can occur if a wrapper element uses border-radius in combination with overflow: hidden when the wrapper contains content that is equal to or larger than the wrapper size.

UPDATE 17/12 14:14

Neither the use of overflow: hidden in the wrapper element, nor the use of border-radius on the contained image (or any other child element) seems to be the reason for this, as they can be interchanged and the pixelated edge will still appear.

This, apparently, indicates that this problem is caused only by the fact that 2 DOM elements are in the same place when any kind of boundary radius is applied to the wrapper element and the visible area of ​​the child is limited by the parent.

+6
source share
4 answers

This seems like a really “feature” of how the browser handles border-radius to give a smooth edge to the rounded corners of the container. The background of the image is smoothed the same way (but since it is transparent it has no effect), as you can see, setting the background color to img.

When the border is smoothed, it “bleeds” into the background to soften the edges, and therefore you see that around the image like an “uneven” ring is almost the same as you see the crown around the moon during a total solar eclipse.

the problem always exists, whether the smoothing object is covered or not, if you have to draw a circle and then smooth it, you will see that the circle is slightly narrower than the smoothed version. Most anti-aliasing algorithms combine the surrounding pixels of an object, rather than those contained in it.

To overcome this, you need to either make the image large enough to cover the space occupied by the smooth edge, or reduce the container so that the smooth area is smaller than the image.

0
source

http://codepen.io/marczking/pen/KwMgaR

So, after the game (using background-image and pseudo-elements, nothing changes ...), you noticed that this light border is visible only if you use round corners. So I assume that it should do the way the browser renders CSS, nothing wrong with CSS rules ^^)

 <figure> <figcaption>Demo</figcaption> </figure> figure { background-color: red; width: 400px; height: 400px; border-radius: 100px; position: relative; /* For caption */ } figure::before { content: ""; position: absolute; left: 0; top: 0; right: 0; bottom: 0; background: url("http://placehold.it/400x400") no-repeat; border-radius: 100px; /* Forced on image for smooth transition */ transition: opacity 1s ease-out; } figcaption { position: absolute; top: 100%; left: 0; width: 100%; color: hotpink; text-align: center; transition: top 1s ease-out; } figure:hover::before { opacity: 0; } figure:hover figcaption { top: 50%; } 
0
source

You can add a new tag with opacity 0, after which they disappear with the disappearance of the image.

 figure { width: 400px; height: 400px; border-radius: 50%; overflow: hidden; position: relative; /* For caption */ } background { background-color: red; width: 400px; height: 400px; border-radius: 50%; overflow: hidden; opacity: 0; position: fixed; z-index: 5; transition: opacity 1s ease-out; } img { border-radius: 50%; /* Forced on image for smooth transition */ width: 100%; transition: opacity 1s ease-out; position: relative; z-index: 100; } figcaption { position: absolute; top: 100%; left: 0; width: 100%; color: hotpink; text-align: center; transition: top 1s ease-out; z-index: 10000; } figure:hover img { opacity: 0; } figure:hover background { opacity: 1; } figure:hover figcaption { top: 50%; } 
 <figure> <background></background> <img src="http://placehold.it/400x400" alt> <figcaption>Demo</figcaption> </figure> 

Notice I added the background tag and removed background-color from figure

0
source

I had the same problem and ended up using a pseudo-element instead of a background, sort of like:

 figure::before { content: ''; display: block; background-color: red; width: 400px; height: 400px; transform: scale(0.997); border-radius: 50%; } 

This allowed me to create a “pseudo-background”, which I later squeezed a bit with transform: scale (0.997); , so it will be the same size, but slightly below the visible edge. Of course, in your case, you will also need to position the image absolutely so that it is not clicked below: before.

0
source

Source: https://habr.com/ru/post/979782/


All Articles