Search code examples
htmlcsschromium

"Clipped" Bottom of Circular div When min-height Set


I have this loader (rendered HTML):

<div class="shuffle-loader">
    <span class="shuffle-loader__dot">
      ::after
    </span>
    <span class="shuffle-loader__dot">
      ::after
    </span>
    <span class="shuffle-loader__dot">
      ::after
    </span>
    <span class="shuffle-loader__dot">
      ::after
    </span>
</div>
/* important css snipet: */
.shuffle-loader {
  position: relative;
  display: block;
  height: 4rem;
  width: 4rem;
}
.shuffle-loader__dot::after {
  position: absolute;
  display: block;
  height: 1.5rem;
  width: 1.5rem;
  animation: shuffle 2.4s linear infinite;
  border-radius: 50%;
  content: " ";
}
.shuffle-loader__dot {
  position: absolute;
  display: block;
  height: 100%;
  width: 100%;
}
@keyframes shuffle {
  0%,
  95%,
  100% {
    transform: translate(0, 0);
  }
  /* etc. */
}
/* Plus some .shuffle-loader__dot:nth-child(1)::after selectors for varied colors, etc. See codepen. */

Animation

Works well. However, it seems a certain combination of CSS properties on a wrapping element causes part of the bottom-right circle to get "clipped":

Clipped

.wrapper {
  min-height: 100vh;
  display: flex;
  align-items: center;
  flex-direction: column;
}

If I remove any of these properties from .wrapper, the loader renders just fine (except, of course, that it's not where I want it on the page).

Here's a codepen reproduction of the issue.

This seems to only happen on Chromium browsers. What's going here? Is it just an engine bug?


Update 08/06/2021: the visual effect is only present when the animation is active (i.e. commenting out the animation "fixes" it); I'm guessing it's a chromium rendering bug related to animations.


Solution

  • Found a workaround based on this Chromium bug discussion: adding a rotate(0deg) transformation on the 0% step of the animation.

    @keyframes shuffle {
        0%, 95%, 100% {
            transform: translate(0, 0) rotate(0deg);
        }
      /* etc. */
    

    I don't really understand how, but it works.