.circle
  .camera.-x
    .camera.-y
      .camera.-z
        .particles
          - for (i = 0; i < 200; i++)
            .particle
              .rotate
                .part
                  .rotatefollow
                    .camerafollow.-z
                      .camerafollow.-y
                        .camerafollow.-x
                            .graphic
View Compiled
$cameraX: 20deg;
$particleSize: 12px;
$amplitude: 50px;
$amplitudeDuration: 1000;
$rotateDuration: 10000;
$rotateDurationMin: 5000;

body {
  background: radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%);
  height: 100vh;
  overflow: hidden;
  display: flex;
  justify-content: center;
  align-items: center;
  perspective: 600px;
}

div {
  transform-style: preserve-3d;
}

.particles {
  transform: translateY(-100px);
}

.camera {
  &.-x {
    transform: rotateX(-$cameraX);
  }
}

.camerafollow {
  &.-x {
    transform: rotateX($cameraX);
  }
}

.part {
  position: absolute;
  top: 50%;
  left: calc(50% + 200px);
}

.graphic {
  position: absolute;
  width: $particleSize;
  height: $particleSize;
  background: linear-gradient(0deg, rgba(#555, 1) 0%, rgba(#fff, 1) 100%);
  border-radius: 100%;
  transform: translate(-50%, -50%);
  
  &::before {
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
    top: $amplitude;
    border-radius: 100%;
    background: linear-gradient(0deg, rgba(#fff, 0) 50%, rgba(#fff, 0.1) 100%);
    // filter: blur(2px);
  }
}

.rotate {
  animation: rotation $rotateDuration + 0ms linear infinite reverse;
}

.rotatefollow {
  animation: rotation $rotateDuration + 0ms linear infinite;
}

.particle {
  @for $i from 1 through 200 {
    $delay: (random(99999) + $rotateDuration + $rotateDurationMin) * -1ms;
    $duration: random($rotateDuration) + $rotateDurationMin + 0ms;
    $r: random(100) + 100;
    $g: random(100) + 100;
    $b: random(150) + 100;

    &:nth-child(#{$i}) {
      .part {
        left: calc(50% + #{random($amplitude * 2) + 180}px);
      }
      
      .rotate,
      .rotatefollow {
        animation-delay: $delay;
        animation-duration: $duration;
      }
      
      .graphic {
        background: linear-gradient(0deg, rgba($r - 50, $g - 50, $b - 50, 1) 0%, rgba($r + 50, $g + 50, $b + 50, 1) 100%);
        animation: amplitude $amplitudeDuration + 0ms $delay cubic-bezier(0.445, 0.050, 0.550, 0.950) infinite alternate;
        
        &::before {
          background: linear-gradient(0deg, rgba($r, $g, $b, 0) 50%, rgba($r, $g, $b, 0.3) 100%);
           animation: amplitudeShadow $amplitudeDuration + 0ms $delay cubic-bezier(0.445, 0.050, 0.550, 0.950) infinite alternate;
        }
      }
    }
  }
}

@keyframes rotation {
  0% {
    transform: rotateY(0deg);
  }
  
  100% {
    transform: rotateY(360deg);
  }
}

@keyframes amplitude {
  0% {
    transform: translateY(0px);
  }
  
  100% {
    transform: translateY($amplitude);
  }
}

@keyframes amplitudeShadow {
  0% {
    opacity: 0;
    transform: translateY($amplitude * 2);
  }
  
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}


View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.