Overflow hidden does not fully hide parent div with border radius

Viewed 338

I am getting some residual overflow from my simple layout below. Though minimal, the effect is quite obvious and happens only where I set a border radius. The expected behavior is to have the div class='inner', the white, fully cover div class='outer', the red. However there clearly seems to be residual overflows from both ends of the div.

Example:

.outer {
  background-color: red;
  width: 500px;
  height: 50px;
  position: relative;
  overflow: hidden;
  border-radius: 5rem;
}
.inner {
  background: white;
  width: 100%;
  height: 100%;
  position: absolute;
}
<div class="outer">
  <div class="inner"></div>
</div>

I am using this as part of a loading bar effect where inner translates as part of an animation during a media play. I have read a couple other problems that involve adding properties like z-index and adding masks but does not work for me. Also read issues with webkit, but have not found anything that works in the case above.

Edit

For clearer illustration refer below:- Overflow hidden is being used so that when inner translates, any overflow is hidden out of the parent div. I am unsure if there are any other ways I can use. Below is an example of having the x-axis translate at 10%. I am trying to achieve the overflow effect without any bleeding from the edges around where border radius is applied.

Translate starts at 0% which is the same as the example above.

This issue was also reported - Issue 491574: border-radius bleeds background-color

And similar to the question - CSS border radius background colour bleed but the use case of overflow does not apply to my case.

.outer {
  background-color: red;
  width: 500px;
  height: 50px;
  position: relative;
  border-radius: 5rem;
  overflow: hidden;
}
.inner {
  background: white;
  width: 100%;
  height: 100%;
  position: absolute;
  transform: translateX(10%);
}
<div class="outer">
  <div class="inner"></div>
</div>

The code above though not in exact flavor is embedded in an app written in ReactJS and I am facing this issue both in Chrome and Mozilla.

1 Answers

The answer I suggested as a duplicate mentions:

The fix would be on a case by case basis... it would be matter of rearranging the elements such that they are a top and bottom rather than a parent and child.

So here is your case fix. You have to have the background red color into a child of the container element... And the progressbar on top of it. Now that the container doesn't have any background color, nothing can bleed due to the anti-aliasing.

Additionnally, if you apply the same border-radius to the "background" div... And a 1px white border... The magic is made.

Below, I animated the width of the .progress-bar on an interval to simulate you react state based animation.

// Simulating an animation... Just for this demo.

let outer = document.querySelector(".outer")
let progress = document.querySelector(".progress-bar")
let outerWidth = outer.getBoundingClientRect().width
let progressWidth = progress.getBoundingClientRect().width

let interval = setInterval(function(){
  progressWidth = progress.getBoundingClientRect().width
  progress.style.width = progressWidth + 10 + "px"
  if(progressWidth > outerWidth) clearInterval(interval)
},500)
.outer {
  background-color: transparent;
  width: 500px;
  height: 50px;
  position: relative;
  border-radius: 5rem;
  overflow: hidden;
}
.progress-background {
  background: red;
  width: calc(100% - 2px);  /* to compensate the white border space */
  height: calc(100% - 2px); /* to compensate the white border space */
  position: absolute;
  border-radius: 5rem;      /* Same radius than the container */
  border: 1px solid white;  /* white border */
}
.progress-bar {
  background: white;
  width: 0;
  height: 100%;
  position: absolute;
  transition: width 1s;  /* Just to have the animation a bit smooter */
}
<div class="outer">
  <div class="progress-background"></div>
  <div class="progress-bar"></div>
</div>

Related