cssflexbox

How can I sync my overlay image with my main circle shape?


I'm trying to replicate the look of a solar eclipse. I have a startup screen that shows a <div> with a border-radius at 50% and a width/height of 20vw. This achieves the rounded look of course and with some box-shadow I pretty much accomplish a look.

But I'd like to enhance the aesthetic with an overlay with some kind of blend-mode (I've tinkered with color-dodge and hard-light so I'll do both somehow)

But I'm running into a wall right now because I cannot fit my eclipse overlay to be perfect around my circle. And I worry that specifically going down to decimal points will just have my design break later because of the units I'm using to make it responsive but I don't know how else I'd try to keep my current layout while syncing my overlay with my shape.

I feel like there must be a better way.

I'm new to stack overflow so I'm sorry if I formatted this poorly. I've attached the overlay image I'm using to this question as well as the image reference I'm trying to replicate

overlay image (incase earlier link doesn't work): https://imgur.com/a/jYMDkaR

.startup-screen {
    position: absolute; 
    z-index: 99;

    display: flex; 
    overflow: hidden;
    align-items: center;
    flex-direction: column;
    justify-content: center;

    width: 100vw;
    height: 100vh;
    background: black;
}


.startup-screen__eclipse {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20%;
    height: 40%;
    padding: 5%;

    box-shadow: 17px 17px 18px rgba(255, 255, 255, 1),
                5px 5px 5px rgb(255, 213, 0),
                6px 6px 6px rgb(66, 230, 255),
                50px 50px 100px rgb(230, 207, 255);

    border-radius: 50%;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    -ms-border-radius: 50%;
    -o-border-radius: 50%;
}


.startup-screen__eclipse__overlay {
    position: absolute;
    width: fit-content;
    height: fit-content;
    border: 2px solid red;
    top: 13%;
    left: 33%;
    /* mix-blend-mode: color-dodge; */
}

.startup-screen__eclipse__overlay img {
    width: 35vw;
    height: 35vw;
    mix-blend-mode: hard-light;
}
<div class="startup-screen" id="startupScreen">
  <div class="startup-screen__eclipse">
      <div class="startup-screen__eclipse__overlay">
          <img src="https://i.sstatic.net/6OwwlZBM.png"> 
      </div>
  </div>
</div>


Solution

  • HTML structure is very important, and the way you have it right now makes it a little bit complicated to do what you're wanting. I would structure my HTML more like in the following example.

    html,
    body {
      margin: 0;
      padding: 0;
    }
    
    .startup-screen {
      display: flex;
      justify-content: center;
      align-items: start;
      width: 100vw;
      min-height: 100vh;
      background: black;
    }
    
    .startup-screen__eclipse-wrapper {
      position: relative;
      border: 2px solid red;
      width: 40%;
      aspect-ratio: 1;
    }
    
    .startup-screen__eclipse-image {
      width: 100%;
      height: 100%;
      object-fit: cover;
      object-position: center;
      mix-blend-mode: hard-light;
    }
    
    .startup-screen__eclipse-overlay {
      position: absolute;
      top: 47%;
      left: 47%;
      width: 52%;
      aspect-ratio: 1;
      transform: translate(-50%, -50%);
      box-shadow: 17px 17px 18px rgba(255, 255, 255, 1), 5px 5px 5px rgb(255, 213, 0), 6px 6px 6px rgb(66, 230, 255), 50px 50px 100px rgb(230, 207, 255);
      border-radius: 50%;
      -webkit-border-radius: 50%;
      -moz-border-radius: 50%;
      -ms-border-radius: 50%;
      -o-border-radius: 50%;
    }
    <div class="startup-screen" id="startupScreen">
      <div class="startup-screen__eclipse-wrapper">
        <img src="https://i.sstatic.net/6OwwlZBM.png" class="startup-screen__eclipse-image">
        <div class="startup-screen__eclipse-overlay"></div>
      </div>
    </div>

    I added a wrapper for both the image and the custom overlay, and then placed the image and overlay as sibling elements inside. That way I can size and position both precisely without worrying about it messing up child elements.