<ul class="cards-container cards">
  <li style="--i: 0;" data-name="Bulbasaur">
    <input type="radio" id="item-1" name="gallery-item" checked>
    <label for="item-1">
      <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/bulbasaur-s.png">
    </label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/bulbasaur-l.png">
    <h2>Bulbasaur</h2>
    <p>Bulbasaur is a grass/poison type Pokémon that evolves into Ivysaur. Bulbasaur is also one of the three starter Pokémon in Red/Blue.</p>
  </li>
  <li style="--i: 1;" data-name="Charmander">
    <input type="radio" id="item-2" name="gallery-item">
    <label for="item-2"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/charmander-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/charmander-l.png" loading="lazy">
    <h2>Charmander</h2>
    <p>Charmander is the fire-type starter Pokémon first seen in Pokémon Red/Blue. Charmander uses the power of its fiery tail to attack the enemy and eventually evolves into Charmeleon.</p>
  </li>
  <li style="--i: 2;" data-name="Charmeleon">
    <input type="radio" id="item-3" name="gallery-item">
    <label for="item-3"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/charmeleon-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/charmeleon-l.png" loading="lazy">
    <h2>Charmeleon</h2>
    <p>Charmeleon is a fire-type Pokémon first found in Pokémon Red/Blue. Charmander evolves from the fire-type starter Pokémon Charmander and eventually into Charizard, all while using his awesome fiery powers.</p>
  </li>
  <li style="--i: 3;" data-name="Squirtle">
    <input type="radio" id="item-4" name="gallery-item">
    <label for="item-4"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/squirtle-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/squirtle-l.png" loading="lazy">
    <h2>Squirtle</h2>
    <p>Squirtle is a Water-type starter Pokémon from the original Pokémon Red/Blue. With enough experience it can evolve into a Wartortle.</p>
  </li>
  <li style="--i: 4;" data-name="Wigglytuff">
    <input type="radio" id="item-5" name="gallery-item">
    <label for="item-5"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/wigglytuff-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/wigglytuff-l.png" loading="lazy">
    <h2>Wigglytuff</h2>
    <p>Wigglytuff is a normal/fairy type Pokémon that evolves from Jigglypuff with a Moon Stone. </p>
  </li>
  <li style="--i: 5;" data-name="Zubat">
    <input type="radio" id="item-6" name="gallery-item">
    <label for="item-6"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/zubat-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/zubat-l.png" loading="lazy">
    <h2>Zubat</h2>
    <p>Zubat is a Poison/Flying type Pokémon that evolves into Golbat.</p>
  </li>
  <li style="--i: 6;" data-name="Sandslash">
    <input type="radio" id="item-7" name="gallery-item">
    <label for="item-7"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/sandslash-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/sandslash-l.png" loading="lazy">
    <h2>Sandslash</h2>
    <p>Sandslash is a ground type Pokémon that evolves from Sandshrew.</p>
  </li>
  <li style="--i: 7;" data-name="Nidorina">
    <input type="radio" id="item-8" name="gallery-item">
    <label for="item-8"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/nidorina-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/nidorina-l.png" loading="lazy">
    <h2>Nidorina</h2>
    <p>Nidorina is a poison type Pokémon that evolves from Nidoran (female) and can evolve into Nidoqueen with a Moon Stone. </p>
  </li>
  <li style="--i: 8;" data-name="Vulpix">
    <input type="radio" id="item-9" name="gallery-item">
    <label for="item-9"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/vulpix-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/vulpix-l.png" loading="lazy">
    <h2>Vulpix</h2>
    <p>Vulpix is a fire type Pokémon that evolves into Ninetales with a Fire Stone.</p>
  </li>
  <li style="--i: 9;" data-name="Gloom">
    <input type="radio" id="item-10" name="gallery-item">
    <label for="item-10"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/gloom-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/gloom-l.png" loading="lazy">
    <h2>Gloom</h2>
    <p>Gloom is a Grass/Poison type Pokémon that evolves from Oddish and can evolve into Vileplume with a Leaf Stone, or Bellossom with a Sun Stone.</p>
  </li>
  <li style="--i: 10;" data-name="Paras">
    <input type="radio" id="item-11" name="gallery-item">
    <label for="item-11"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/paras-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/paras-l.png" loading="lazy">
    <h2>Paras</h2>
    <p>Paras is a Bug/Grass type Pokémon that evolves into Parasect. </p>
  </li>
  <li style="--i: 11;" data-name="Alakazam">
    <input type="radio" id="item-12" name="gallery-item">
    <label for="item-12"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/alakazam-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/alakazam-l.png" loading="lazy">
    <h2>Alakazam</h2>
    <p>Alakazam is a psychic-type pokemon from the original Pokemon Red/Blue. As the evolution of Kadabra, Alakazam is the third in a line of powerful spoon-bending psychics.</p>
  </li>
  <li style="--i: 12;" data-name="Poliwrath">
    <input type="radio" id="item-13" name="gallery-item">
    <label for="item-13"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/poliwrath-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/poliwrath-l.png" loading="lazy">
    <h2>Poliwrath</h2>
    <p>Poliwrath is a water/fighting-type pokemon first found in the original Pokemon Red/Blue. Poliwrath is the evolved form of Poliwag and Poliwhirl, and it loves to get up-close and personal, using its confusing belly to misdirect opponents before it goes in for the final punch.</p>
  </li>
  <li style="--i: 13;" data-name="Mankey">
    <input type="radio" id="item-14" name="gallery-item">
    <label for="item-14"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/mankey-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/mankey-l.png" loading="lazy">
    <h2>Mankey</h2>
    <p>Mankey is a fighting-type pokemon first featured in the original Pokemon Red/Blue. Mankey uses its dense form to the fullest advantage, dodging nimbly as it strikes blows on its opponents.</p>
  </li>
  <li style="--i: 14;" data-name="Tentacruel">
    <input type="radio" id="item-15" name="gallery-item">
    <label for="item-15"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/tentacruel-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/tentacruel-l.png" loading="lazy">
    <h2>Tentacruel</h2>
    <p>Tentacruel is a water/poison-type pokemon first found in the original Pokemon Red/Blue. Tentacruel is the evolution of Tentacool, its spindly tentacles more numerous and more poisonous.</p>
  </li>
  <li style="--i: 15;" data-name="Farfetch'd">
    <input type="radio" id="item-16" name="gallery-item">
    <label for="item-16"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/farfetch_d-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/farfetch_d-l.png" loading="lazy">
    <h2>Farfetch'd</h2>
    <p>Farfetch'd is a Normal/Flying type Pokémon. Farfetch'd is very protective of its leek, and can use the vegetable to attack opponents, even as Farfetch'd moves out of harm's way.</p>
  </li>
  <li style="--i: 16;" data-name="Voltorb">
    <input type="radio" id="item-17" name="gallery-item">
    <label for="item-17"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/voltorb-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/voltorb-l.png" loading="lazy">
    <h2>Voltorb</h2>
    <p>Voltorb is an electric-type pokemon first found in the original Pokemon Red/Blue. Voltorb is commonly mistaken for a hidden pokeball, often to the detriment of the one who finds it.</p>
  </li>
  <li style="--i: 17;" data-name="Rhyhorn">
    <input type="radio" id="item-18" name="gallery-item">
    <label for="item-18"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/rhyhorn-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/rhyhorn-l.png" loading="lazy">
    <h2>Rhyhorn</h2>
    <p>Rhyhorn is a ground/rock-type pokemon first found in the original Pokemon Red/Blue. Rhyhorn has a short stocky body that it uses to full advantage by rushing opponents to hit them with his horn-adorned head. It evolves into Rhydon when it reaches level 42. </p>
  </li>
  <li style="--i: 18;" data-name="Tangela">
    <input type="radio" id="item-19" name="gallery-item">
    <label for="item-19"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/tangela-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/tangela-l.png" loading="lazy">
    <h2>Tangela</h2>
    <p>Tangela is a grass-type pokemon first found in the original Pokemon Red/Blue. Tangela uses vines growing out of its body to obscure it so that only its eyes and feet can be seen. </p>
  </li>
  <li style="--i: 19;" data-name="Mr. Mime">
    <input type="radio" id="item-20" name="gallery-item">
    <label for="item-20"><img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/mr_mime-s.png"></label>
    <img src="https://raw.githubusercontent.com/cbolson/assets/refs/heads/main/codepen/pokemon/mr_mime-l.png" loading="lazy">
    <h2>Mr. Mime</h2>
    <p>Mr. Mime is a psychic-type pokemon from the original Pokemon Red/Blue. Like his name indicates, this pokemon doesn't say much - but watch out! Mr. Mime can copy even the most deadly attack and use it as its own. </p>
  </li>
</ul>
View Compiled
@import url(https://fonts.bunny.net/css?family=abel:400);

/* Hide radio buttons */
input[type="radio"] {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

.cards {
  --base-rotation: 0deg;
  --full-circle: 360deg;
  --items: 20;
  --radius: 30vw;
  --duration: 300ms;

  --cards-container-size: calc(var(--radius) * 2);
  --thumb-size: 30px;
  --image-size: calc(var(--radius));
  --image-y: 0%;
  --labels-offset: calc(var(--radius) * -1);
  --title-top: calc(var(--thumb-size) * -3);
  --info-top: calc(100% + 2rem);
  --info-width: 100%;

  position: fixed;
  inset: 0;
  margin: auto;
  width: var(--cards-container-size);
  height: var(--cards-container-size);
  aspect-ratio: 1;
  border-radius: 50%;
  perspective: 1000px;
  transition: transform 0.3s ease-in-out var(--duration);
  list-style: none;
}

@media (min-width: 800px) {
  .cards {
    --radius: 30vw;
    --thumb-size: 40px;
    --title-top: 2rem;
  }
}
@media (min-width: 1200px) {
  .cards {
    --radius: 20vw;
    --thumb-size: 50px;
    --image-y: -20%;
    --info-width: min(100% - 2rem, 65%);

    --info-top: calc(var(--image-size) * 1.3);
  }
}

.cards li {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  transform-origin: center;
  display: grid;
  place-content: center;
  transform: rotate(calc(var(--i) * 360deg / var(--items)));
  pointer-events: none;
}

.cards li > label {
  position: absolute;
  inset: 0;
  margin: auto;
  transform: translateY(var(--labels-offset));
  width: var(--thumb-size);
  height: var(--thumb-size);
  cursor: pointer;
  pointer-events: initial;
  /*outline: 1px dashed red;*/
  transition: var(--duration) ease-in-out;
}
/* thumbs */
.cards li > label > img {
  transform-origin: center;
  width: 100%;
  scale: var(--label-scale, 1);
  opacity: var(--label-opacity, 1);
  transition: scale var(--duration) ease-in-out,
    opacity var(--duration) ease-in-out;
}
/* redudce scale of all thumbs */
.cards:has(label:hover) label {
  --label-scale: 0.75;
}
/* enlarge thumbs either side of hovered */
.cards li:has(+ li > label:hover) > label,
.cards li:has(label:hover) + li > label {
  --label-scale: 1.25;
}
/* hovered thumb */
.cards li > label:hover img {
  --label-scale: 1.5;
}
/* main image */
.cards > li > img {
  width: var(--image-size);
  height: var(--image-size);
  object-fit: contain;
  z-index: 52;

  transform: translateY(var(--image-y));
  transition-property: opacity, scale, width, height, transform, filter;
  transition-duration: var(--duration);
  transition-timing-function: ease-in-out;
  transition-delay: var(--item-delay, 0ms), var(--item-delay, 0ms), 0ms, 0ms, 0ms,
    0ms;

  pointer-events: initial;
  opacity: var(--item-opacity, 0);
  scale: var(--item-scale, 0);
  filter: drop-shadow(0px 0px 5px rgba(255 255 255 / 0.25));
}

.cards > li:has(:checked) > img:hover {
  transform: translateY(var(--image-y)) rotateY(-30deg) rotateX(-5deg);
  transition-delay: 0ms;
  filter: drop-shadow(15px 10px 5px rgba(255 255 255 / 0.25));
}

.cards > li > h2,
.cards > li > p {
  position: absolute;
  left: 50%;
  text-align: center;
  transform: translate(-50%, 0);
  transform-origin: center;
}
.cards > li > h2 {
  top: var(--title-top);
  opacity: var(--title-opacity, 0);
  translate: 0 var(--title-y, -30px);
  transition: var(--duration) ease-in-out var(--title-delay, 0ms);
}
.cards > li > p {
  top: var(--info-top);
  margin: 0 auto;
  width: var(--info-width);
  z-index: 2;
  font-size: clamp(0.8rem, 3.5vw + 0.05rem, 1.1rem);
  text-wrap: balance;
  opacity: var(--info-opacity, 0);
  translate: 0 var(--info-y, 30px);
  transition: var(--duration) ease-in-out var(--info-delay, 0ms);
}

/* update custom properties for checked item */
li:has(input:checked) {
  --label-opacity: 0.25;
  --label-scale: 1;
  --item-scale: 1;
  --item-opacity: 1;
  --item-delay: calc(var(--duration) * 2);
  --title-opacity: 1;
  --title-y: 0;
  --title-delay: calc(var(--duration) * 3);
  --info-opacity: 1;
  --info-y: 0;
  --info-delay: calc(var(--duration) * 3);
  /*outline: 1px dashed red;*/
  z-index: 99;
}

/* rotate container based on checked radio */
.cards:has(input:checked) {
  transform: rotate(
    calc(
      var(--base-rotation) - (var(--index) * var(--full-circle) / var(--items))
    )
  );
}
/*
this would be so much simpler if we could use counter values as custom property values
*/
.cards:has(input#item-1:checked) {
  --index: 0;
}
.cards:has(input#item-2:checked) {
  --index: 1;
}
.cards:has(input#item-3:checked) {
  --index: 2;
}
.cards:has(input#item-4:checked) {
  --index: 3;
}
.cards:has(input#item-5:checked) {
  --index: 4;
}
.cards:has(input#item-6:checked) {
  --index: 5;
}
.cards:has(input#item-7:checked) {
  --index: 6;
}
.cards:has(input#item-8:checked) {
  --index: 7;
}
.cards:has(input#item-9:checked) {
  --index: 8;
}
.cards:has(input#item-10:checked) {
  --index: 9;
}
.cards:has(input#item-11:checked) {
  --index: 10;
}
.cards:has(input#item-12:checked) {
  --index: 11;
}
.cards:has(input#item-13:checked) {
  --index: 12;
}
.cards:has(input#item-14:checked) {
  --index: 13;
}
.cards:has(input#item-15:checked) {
  --index: 14;
}
.cards:has(input#item-16:checked) {
  --index: 15;
}
.cards:has(input#item-17:checked) {
  --index: 16;
}
.cards:has(input#item-18:checked) {
  --index: 17;
}
.cards:has(input#item-19:checked) {
  --index: 18;
}
.cards:has(input#item-20:checked) {
  --index: 19;
}

/* general styling */
*,
::before,
::after {
  box-sizing: border-box;
}
:root {
  --clr-bg: #000;
  --clr-primary: rgb(248, 243, 243);
}
html {
  background-color: var(--clr-bg);
  font-family: "Abel", sans-serif;
}

body {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  line-height: 1.4;
  color: var(--clr-primary);
  padding: 1rem;
  margin: 0;
}
/* DEBUG - cross-hairs for center of body */
/*
body::after,
body::before{
  content: '';
  position: absolute;
  background-color: green;
  opacity: .5;
  z-index: -10;
}
body::before{
  inset: 0 50%;
  width: 1px;
}
body::after{
  inset: 50% 0;
  height: 1px;
}
*/
/* nothing to see here */

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.