<main>
  <h1>Performant Shadow Animation</h1>
  <p>
    This is a comparsion of animating:
  <ul>
    <li><code>box-shadow</code>,</li>
    <li>the <code>opacity</code> of an <code>::after</code> pseudo-element which has a bigger box shadow,</li>
    <li>and <code>filter:drop-shadow()</code></li>
  </ul>
  </p>
  <div class="img-container">
    <img src="https://cdn.imgpaste.net/2021/01/17/jKprq.png" alt="perf comparsion different properties" />
  </div>
  <p>
    The image above summarises the findings for a low end mobile device. The green striped bars indicate that activity is off the main thread for the pseudo-element and <code>drop-shadow()</code> animations, which accounts for the major difference in performance.</p>
  <p>The smoothest animation is the pseudo-element. The most efficient is
    <code>drop-shadow()</code> (least amount of painting/rendering time). The best overall choice is the pseudo-element.
  </p>
  <p>You check out examples of each method below.</p>
  <h2>Hover animation with <code>box-shadow</code></h2>
  <div class="container">
    <div class="box boxShadow"></div>
    <div class="box boxShadow"></div>
  </div>
  <pre><code class="language-css">:root {
	--intial-state: 0 2px 2px rgba(0, 0, 0, 0.2);
	--final-state: 0 5px 15px rgba(0, 0, 0, 0.4);
}

.boxShadow {
	box-shadow: var(--intial-state);
	transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
}

.boxShadow:hover {
	box-shadow: var(--final-state);
}</code></pre>
  <h2>Hover animation with <code>::after</code> pseudo-element</h2>
  <div class="container">
    <div class="box pseudo"></div>
    <div class="box pseudo"></div>
  </div>
  <pre><code class="language-css">:root {
	--intial-state: 0 2px 2px rgba(0, 0, 0, 0.2);
	--final-state: 0 5px 15px rgba(0, 0, 0, 0.4);
}

.pseudo {
	box-shadow: var(--intial-state);
}

.pseudo::after {
	content: "";
	border-radius: 5px;
	position: absolute;
	z-index: 1;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	box-shadow: var(--final-state);
	opacity: 0;
	transition: opacity 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
}

.pseudo:hover::after {
	opacity: 1;
}
</code></pre>
  <h2>Hover animation with <code>drop-shadow()</code></h2>
  <div class="container">
    <div class="box dropShadow"></div>
    <div class="box dropShadow"></div>
  </div>
  <pre><code class="language-css">:root {
	--intial-state: 0 2px 2px rgba(0, 0, 0, 0.2);
	--final-state: 0 5px 15px rgba(0, 0, 0, 0.4);
}

.dropShadow {
	filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
	transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
}

.dropShadow:hover {
	filter: drop-shadow(0 5px 15px rgba(0, 0, 0, 0.3));
}
</code></pre>
</main>
:root {
  --intial-state: 0 2px 2px rgba(0, 0, 0, 0.2);
  --final-state: 0 5px 15px rgba(0, 0, 0, 0.4);
}

.container {
  display: flex;
  justify-content: center;
}

.box {
  position: relative;
  display: inline-block;
  width: 100px;
  height: 100px;
  background-color: rgb(56, 159, 255);
  border-radius: 5px;
  margin: 0 20px;
}

.boxShadow {
  box-shadow: var(--intial-state);
  transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
}

.boxShadow:hover {
  box-shadow: var(--final-state);
}

.pseudo {
  box-shadow: var(--intial-state);
}

.pseudo::after {
  content: "";
  border-radius: 5px;
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  box-shadow: var(--final-state);
  opacity: 0;
  transition: opacity 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
}

.pseudo:hover::after {
  opacity: 1;
}

.dropShadow {
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
  transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
}

.dropShadow:hover {
  filter: drop-shadow(0 5px 15px rgba(0, 0, 0, 0.3));
}

h1,
h2 {
  text-align: center;
}

main {
  width: calc(100% - 10px);
  margin: 0 auto;
  max-width: 1200px;
  font-size: calc(1rem + 0.25vw);
  font-family: Roboto, Georgia, Times, serif;
}

.img-container {
  overflow-x: scroll;
}

img {
  display: block;
  width: 1159px;
}
Run Pen

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/themes/prism-tomorrow.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/prism/1.4.1/prism.min.js