Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jagged "border" showing due to background colour on wrapper element with border-radius: 50%;

As I was in the process of trying to make an animated figure (transitions on hover), I found out that the background of my <figure> is showing near the edges when I apply border-radius: 50% to it, even though my image should be taking up all available space.

For a quick demo that illustrates the problem, please look at 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%;
}

Please note: I know that placing the background-color on figure:hover is a work-around, but I am more interested in the reason why this "jagged border"-like look is appearing.

My guess is that it has to do with AA rendering (or something related) of the browser and that it treats the <figure> element differently than a media element such as <img>, but I can't find any proof of this online. Is this a bug, is it a "feature", or is it something I can actually fix?

Lastly, I also know that I could have used transform: translateY(); here for the animation, but that's not part of my question so please don't provide it as an answer.

UPDATE 17/12 14:03

It appears that this issue is not exclusive to border-radius: 50%. The issue can occur when any wrapping element uses border-radius in combination with overflow: hidden, when the wrapper contains content that is equal or bigger than the wrapper's dimensions.

UPDATE 17/12 14:14

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

This seems to indicate that this issue is solely caused by 2 DOM elements being in exactly the same place, when any sort of border-radius is applied to the wrapper element and the visible area of the child is limited to that of the parent's.

like image 315
Simon V. Avatar asked Dec 17 '14 12:12

Simon V.


1 Answers

I've been having same issue and ended up using pseudo element instead of background, kinda like that:

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

This allowed me to create 'pseudo background' which I later shrinked a little bit with transform: scale(0.997); so it will be just the same size but a bit below visible edge. Of course in your case you would also need to position image absolutely so it is not pushed below by this ::before.

like image 56
waterplea Avatar answered Oct 16 '22 10:10

waterplea