<div class="z">
  <div class="x">
    <div class="y">
      <b class="r"></b>
    </div>
  </div>
  <div class="x">
    <div class="y">
      <span class="r"></span>
    </div>
  </div>
  <div class="x">
    <div class="y">
      <p class="r"></p>
    </div>
  </div>
</div>
:root {
  --primary: hsl(153, 70%, 60%);
  --secondary: hsl(323, 70%, 60%);
  --tertiary: hsl(43, 70%, 60%);
  --x: 0;
  --y: 0;
  --z: 0;
  --r: 0deg;
  --rotation: var(--r);
  --scale: .875;
  
  --cubic1-1: .85;
  --cubic1-2: .18;
  --cubic1-3: .44;
  --cubic1-4: 1.2;
  
  --cubic2-1: .75;
  --cubic2-2: -0.35;
  --cubic2-3: 0;
  --cubic2-4: .9;
  
  --cubic1-change: 1;
  --cubic2-change: 1;
  
  --dim: 6vmin;
}
span, p, b, i {
  display: block;
  width: var(--dim);
  height: var(--dim);
  border-radius: 10%;
  background: var(--primary);
}
p {
  background: var(--secondary);
}
b {
  background: var(--tertiary);
}
div {
  will-change: transform;
  transition: transform 1200ms ease-in-out;
}
.x {
  transform: translateX(calc(var(--x) * 1px));
  transition-timing-function: cubic-bezier(.85,.18,.44,1.2);
  transition-timing-function: cubic-bezier(var(--cubic1-1),var(--cubic1-2),var(--cubic1-3),var(--cubic1-4));
  position: absolute;
}
.advanced-calc .x {
  transition-timing-function: 
    cubic-bezier(
      calc(var(--cubic1-1) * var(--cubic1-change)),
      calc(var(--cubic1-2) * var(--cubic1-change)),
      calc(var(--cubic1-3) * var(--cubic1-change)),
      calc(var(--cubic1-4) * var(--cubic1-change)));
}
.x:nth-of-type(2) {
  --cubic1-change: .9;
}
.x:nth-of-type(3) {
  --cubic1-change: .8;
}
.y {
  transform: translateY(calc(var(--y) * 1px));
  transition-timing-function: cubic-bezier(.75,-0.35,.07,.9);
  transition-timing-function: cubic-bezier(var(--cubic2-1),var(--cubic2-2),var(--cubic2-3),var(--cubic2-4));
}

.advanced-calc .y {
  transition-timing-function: 
    cubic-bezier(
      calc(var(--cubic2-1) * var(--cubic2-change)),
      calc(var(--cubic2-2) * var(--cubic2-change)),
      calc(var(--cubic2-3) * var(--cubic2-change)),
      calc(var(--cubic2-4) * var(--cubic2-change)));
}
.x:nth-of-type(2) .y {
  --cubic2-change: .9;
}
.x:nth-of-type(3) .y {
  --cubic2-change: .8;
}
.let-us-move-it .y {
  //transition-timing-function: linear;
}
.z {
  transform: translateZ(calc(var(--z) * 1px));
  transition-timing-function: ease-in-out;
}

.r {
  transform: translate3d(-50%, -50%, 0) scale(var(--scale));
  transform: translate3d(-50%, -50%, 0) scale(var(--scale)) rotate(var(--rotation));
  transition: transform 1200ms ease-in-out;
}
b.r {
  --scale: .95;
}
p.r {
  --scale: .8;
}
.advanced-calc b.r {
  --rotation: calc(var(--r) * .5);
}
.advanced-calc p.r {
  --rotation: calc(var(--r) * 1.5);
}


body {
  min-height: 100vh;
  overflow: hidden;
  background: hsl(203, 28%, 12%);
  perspective: 1000px;
  perspective-origin: center center;
}
document.documentElement.classList.add(isCalcSupported() ? 'advanced-calc' : 'basic-calc');

if (window.PointerEvent) {
  document.body.addEventListener('pointerup', jumpFromInteraction);
} else {
  document.body.addEventListener('mouseup', jumpFromInteraction);
  document.body.addEventListener('touchend', jumpFromInteraction);
}

var style = document.documentElement.style;

function jumpFromInteraction(e) {
  if (beforeInteractionInterval) {
    clearInterval(beforeInteractionInterval);
    beforeInteractionInterval = undefined;
  }
  jump(e);
}

//Translate to the new point
function jump(e) {
  var x = e.clientX || e.changedTouches[0].clientX;
  var y = e.clientY || e.changedTouches[0].clientY;
  var z = 0;//Math.random() * (-300);
  var r = Math.random() * 720 - 360;
  
  style.setProperty('--x', x);
  style.setProperty('--y', y);
  //style.setProperty('--z', z);
  style.setProperty('--r', r + 'deg');
  
  changeEasing();
}


//Change the four points of the cubic-bezier to up the non-linear ante
function changeEasing() {
  style.setProperty('--cubic1-1', part(.8, .15));
  style.setProperty('--cubic1-2', part(.1, .2));
  style.setProperty('--cubic1-3', part(.35, .25));
  style.setProperty('--cubic1-4', part(1, .25));
  
  style.setProperty('--cubic2-1', part(.7, .15));
  style.setProperty('--cubic2-2', part(-.35, .35));
  style.setProperty('--cubic2-3', part(0, .1));
  style.setProperty('--cubic2-4', part(.8, .2));
}
function part(min, offset) {
  return Math.random() * offset + min;
}





//Do automatic animations while waiting for viewer to interact
setTimeout(freeJump,100);
let beforeInteractionInterval = setInterval(freeJump, 1200);
let freeJumpCount=0;

function freeJump() {
  jump({
    clientX: Math.floor(((freeJumpCount) % 4 < 2 ? (Math.random() * .3 + .7) : (Math.random() * .4 + .01)) * window.innerWidth),
    clientY:  Math.floor(((freeJumpCount++) % 2 == 0 ? (Math.random() * .2 + .8) : (Math.random() * .2 + .01)) * window.innerHeight)
  });
}



//Check if Calc is supported inside cubic-bezier (ultimately a check to see if we are in Firefox)
function isCalcSupported() {
  document.body.style.transitionTimingFunction = 'cubic-bezier(calc(1 * 1),calc(1 * 1),calc(1 * 1),calc(.5 * 1))';
  return getComputedStyle(document.body).transitionTimingFunction != 'ease';
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.