<div class="penrose">
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="ball"></div>
</div>
*, *::before, *::after {
  padding: 0;
  margin: 0 auto;
  box-sizing: border-box;
}

body {
  background-color: #111;
  color: #fff;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

$speed: 20s;

.penrose {
  position: relative;
  filter: drop-shadow(0 0 25px #000) drop-shadow(0 0 50px hsl(40, 75%, 15%));
}

.triangle {
  position: absolute;

  &:nth-child(-n + 3) {
    width: 146px; height: 36px;
    transform: translate(-50%, -50%) rotate(var(--aAngle)) translateX(31.4px) translateY(36px) skewX(-30deg);
    background-image: linear-gradient(to right, #000a, #0000 50%);
    animation: triangleZ1 $speed infinite step-end;

    @keyframes triangleZ1 {
      0%, 85% { z-index: 2; }
      25%  { z-index: -2; }
    }
  }

  &:nth-child(n + 4) {
    width: 50px; height: 205px;
    transform: translate(-50%, -50%) rotate(var(--aAngle)) translateX(59.2px) translateY(-48.5px) skewX(30deg);
    background-image: linear-gradient(#000a, #0000 50%);
    animation: triangleZ2 $speed infinite step-end;

    @keyframes triangleZ2 {
      0%, 50% { z-index: 2;}
      33.333% { z-index: -2;}
    }
  }

  &:nth-child(3n) { background-color: hsl(40, 75%, 50%); --aAngle: 0;          animation-delay: $speed * -1 / 3; }
  &:nth-child(3n + 1) { background-color: hsl(40, 75%, 20%); --aAngle: 120deg; animation-delay: $speed * -0 / 3; }
  &:nth-child(3n + 2) { background-color: hsl(40, 75%, 40%); --aAngle: 240deg; animation-delay: $speed * -2 / 3; }
}

.ball {
  position: absolute;
  width: 30px; height: 30px;
  animation: ball $speed infinite ease-in-out;

  @keyframes ball {
    0%, 100% { transform: translate(-50%, -50%) translateX(0px) translateY(-171px); }
    8.333% { transform: translate(-50%, -50%) translateX(110px) translateY(20px); }
    16.666% { transform: translate(-50%, -50%) translateX(-30px) translateY(20px); }
    25% { transform: translate(-50%, -50%) translateX(35px) translateY(-125px); }
    33.333% { transform: translate(-50%, -50%) translateX(148px) translateY(90px); }
    41.666% { transform: translate(-50%, -50%) translateX(-80px) translateY(90px); }
    50% { transform: translate(-50%, -50%) translateX(0px) translateY(-50px); }
    58.333% { transform: translate(-50%, -50%) translateX(110px) translateY(90px); }
    66.666% { transform: translate(-50%, -50%) translateX(-148px) translateY(90px); }
    75% { transform: translate(-50%, -50%) translateX(-25px) translateY(-115px); }
    83.333% { transform: translate(-50%, -50%) translateX(50px) translateY(12px); }
    91.666% { transform: translate(-50%, -50%) translateX(-110px) translateY(12px); }
  }

  &::before {
    content: '';
    position: absolute;
    top: -50%; left: -100%;
    width: 300%; height: 200%;
    background-image: radial-gradient(#0005, #0000 50%);
    animation: shadowDir $speed infinite step-end;

    @keyframes shadowDir {
      0%      { transform: rotate(0deg) skewX(30deg); }
      33.333% { transform: rotate(120deg) skewX(30deg); }
      66.666% { transform: rotate(60deg) skewX(30deg); }
    }
  }

  &::after {
    content: '';
    position: absolute;
    width: 100%; height: 100%;
    border-radius: 50%;
    background-image: radial-gradient(circle at top, lightblue, #000 100%);
  }
}
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://assets.codepen.io/1948355/twitterButton-2.1.0.js