skip to Main Content

I would like to achieve the following animation with CSS:

  • From the center the circle scales to 100%, so the entire circle is filled with a color
  • Then again from the center the fill deformed into a stroke around the circle

I thought the best way is to use the before or after pseudo, so you can animate to circles. The problem I think I run into is that the animation on the parent is also used within the pseudo class.

If there is a better way to achieve this, I am open for suggestions 🙂

https://codepen.io/Caspert/pen/JjaMgKe

HTML:
<div class="circle"></div>

SCSS:

@keyframes parentFromCenter {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes childFromCenter {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}


.circle {
  height: 200px;
  width: 200px;
  box-sizing: border-box;
  border-radius: 50vh;
  overflow: hidden;
  position: relative;
  background: black;
  animation: parentFromCenter 1s ease-in;

  &::before {
    content: "";
    height: 90%;
    width: 90%;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: white;
    border-radius: inherit;
    animation: childFromCenter 1s ease-in;
  }
}

4

Answers


  1. You don’t need to use pseudo-elements. You can just add another div inside the circle and animate each of them like so:

    <div class="circle">
      <div class="inner"></div>
    </div>
    

    Also, add the forwards keyword to the animation so the elements keep the styling from the animation.

    Here is an example: https://codepen.io/raul-rogojan/pen/dyqJxVB

    Login or Signup to reply.
  2. If you want the inner circle to be a cutout and see the content behind u can achieve the same effect using box-shadow This is the update

    .circle2 {
     --circle-size: 200px;
     --fill-circle: calc(circle-size / 2);
     --stroke-size: 10px;
     width: var(--circle-size);
     height: var(--circle-size);
     background-color: pink;
     border-radius: 100vh;
     background: transparent;
     box-shadow: inset 0 0 0 var(--circle-size) lightblue;
     animation: parentFromCenter 1s ease-in forwards, shadow 1s 1s ease-in forwards; 
    }
    

    I have also updated the code pen: https://codepen.io/raul-rogojan/pen/dyqJxVB

    Login or Signup to reply.
  3. I’ll throw in my two cents…

    .circle{
      width: 10px;
      aspect-ratio: 1/1;
      border-radius: 50%;
      box-sizing: border-box;
      
      animation: expanding 2s linear infinite;
      transform: translate(-50%, -50%);
      left: 100px;
      top: 100px;
      position: absolute;
    }
    
    @keyframes expanding{
      0%{
        width: 10px;
        border: 6px solid blue;
      }
      50%{
        width: 200px;
        border: 102px solid blue;
      }
      100%{
        width: 200px;
        border: 5px solid blue;
      }
    }
    <div class="circle">
    
    </div>
    Login or Signup to reply.
  4. Using pseudo elements for styling seems like a good idea – but I’d go further and completely separate out the animation styling from the actual element.

    This snippet keeps the element itself at its full dimensions and animates the before an after pseudo elements to grow from scale 0 to scale 1.

    The before pseudo element is black and starts to grow immediately. The after pseudo element is white and waits 1 second before starting to grow.

    body {
      /* just for demo */
      width: 100vw;
      height: 100vh;
    }
    
    @keyframes grow {
      0% {
        transform: scale(0);
      }
      100% {
        transform: scale(1);
      }
    }
    
    .circle {
      height: 200px;
      width: 200px;
      box-sizing: border-box;
      border-radius: 50vh;
      overflow: hidden;
      position: relative;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    
    .circle::before,
    .circle::after {
      content: '';
      position: absolute;
      animation: grow 1s ease-in forwards;
      border-radius: inherit;
      transform: scale(0);
      z-index: -1;
    }
    
    .circle::before {
      top: 0;
      left: 0;
      height: 100%;
      width: 100%;
      background: black;
    }
    
    .circle::after {
      height: 90%;
      width: 90%;
      top: 5%;
      left: 5%;
      background: white;
      animation-delay: 1s;
    }
    <div class="circle"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search