Circular reveal animation: a simple (and dirty) way

  • css
posted on 22nd April 2022 ∙ by Hynek Svacha ∙ 2 min read

This post is inspired by a YouTube video by Paul Lewis, titled Creating a circular reveal animation with JavaScript and CSS!. He is explaining how to make a cool image animation using CSS and Javascript.

Paul’s approach is quite sophisticated. He is putting the image into a circular container that is a little bit smaller than the image itself. When the animation is triggered, the container is expanding, while the contained image is contracting at the same speed. This is creating the “reveal” effect. Paul is using JavaScript and some clever math to sync the easing of the two motions. Just take a look:

The video made me wonder why Paul is using such a complex approach. Most likely because he’s a decent guy who plays by the rules. And the basic rule of CSS animations is that you will animate only transform or opacity (if you are wondering why, here is the detailed explanation).

But I am nowhere near as smart as Paul, hence I’d rather avoid such sophisticated stuff. So I decided to play dirty. Hold onto your hats—here is a way to replicate the reveal effect using a box shadow animation!

First things first, the CSS:

:root {
  --dimensions: 200px;
  --bgColor: white;
  --cropSize: calc(var(--dimensions) / 10);
}

.container {
  position: relative;
  height: var(--dimensions);
  width: var(--dimensions);
}

.container::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  border-radius: 50%;
  z-index: 1;
  box-shadow: inset 0 0 0 var(--cropSize) var(--bgColor);
  transition: box-shadow 0.3s ease;
}

.container:hover::after {
  box-shadow: inset 0 0 0 0 var(--bgColor);
}

.image {
  position: absolute;

  /* We need to center the image (*inset*) and make it a little bit smaller than the container (exactly: 1 px on both sides, so 2 px in sum). If we skip this, an ugly, crispy 'halo' would appear (try it yourself). */
  inset: 1px;
  max-width: calc(100% - 2px);
  max-height: calc(100% - 2px);

  z-index: -1;
  border-radius: 50%;
}

And here is the markup:

<div class="container">
  <img
    class="image"
    src="http://placekitten.com/300/300"
    alt="a furry qute kitt'n"
  />
</div>

Demo

a verry qiute kitton

👍 Enjoy!


If you find anything in this post that should be improved (either factually or in language), feel free to edit it on Github .