Animating scale on circle with centered text on top, with mix-blend-mode

79 Views Asked by At

I'm trying to animate a button that should have a black circle in the bottom layer with centered white text on top. The black circle should scale from full size to smaller size, while the text should use mix-blend-mode so that it stays white when part of the text is still in the circle, and black when part of the text is outside the circle.

Here's a GIF to visualize the desired effect: http://g.recordit.co/bg4Jf7ivZ3.gif

I've tried to create this using this code:

.menu {
  position:fixed;
  bottom:0;
  left:0;
  background-color:white;
  padding:4rem;
}

.container {
    width:50px;
    height:50px;
    position:relative;
}

.container:after {
        z-index:-1;
        position:absolute;
        border-radius:50px;
        top:0;
        left:0;
        right:0;
        bottom:0;
        content:"";
        background:black;
        animation:scale 1s linear alternate-reverse infinite;
}

    .text {
        z-index:1;
        color:white;
        position:absolute;
        top:50%;
        left:50%;
        transform:translate(-50%,-50%);
        mix-blend-mode: difference;
    }
    
    @keyframes scale {
    from {
        margin:0;
    }
    to {
        margin:15px;
    }
}
<div class="menu">

<div class="container">
  <div class="text">Information</div>
</div>

</div>

The reason I animate the margin in the @keyframes is because using transform removes the mix-blend-mode for some reason. Also seems like there needs to be a wrapper (in this case .menu) with a background-color set in order for the text to change color when outside of the circle.

Anyways, this only works in Chrome. Is there any other way to do it that would work in as many browsers as possible?

And is there any way to have the text change it's color when outside the circle without having to set a background-color to a wrapper? I'm placing the button fixed on a page and would prefer if there was a way to not have a solid background-color on it's container, so that it blends with whatever is in the background of the page.

1

There are 1 best solutions below

0
On

Unfortunately you'll run into lack of support for mix-blend-mode and I'm still not convinced the browsers claiming support are fully supported but there's options if say you maybe wanted to fake it with an illusion.

Quickie proof-of-concept that could use some tweeks around centering I'm sure since the measure and arrange pass will probably make it jumpy in firefox but it's just a PoC;

.container {
  margin: 1rem auto;
  border: red 1px dotted;
  height: 15rem;
  width: 15rem;
}

.boundary {
  position: relative;
  border: green 1px dotted;
  height: 100%;
}

.center-it, span, .circle {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

span {
  font-weight: 600;
}

.white-txt {
  width: 8rem;
  text-align: center;
  display: block;
  color: white;
}

.circle {
  height: .5rem;
  width: .5rem;
  background-color: black;
  border-radius: 50%;
  overflow: hidden;
  white-space: no wrap;
  animation: pulse 3s ease infinite;
}

@keyframes pulse {
  50% {
    height: 8rem;
    width: 8rem;
  }
}
<div class="container">
  <div class="boundary">
    <span class="black-txt">Just a test</span>
    <div class="circle">
      <span class="white-txt">Just a test</span>  
    </div>
  </div>
</div>