<div class="outer">
  <div class="shadow"></div>
  <div class="card"></div>
</div>

<div class="output">
  <pre></pre>
</div>
:root {
  --bg-img: url(https://i.pinimg.com/originals/ac/2f/6f/ac2f6f3886f0039d774c263c432222db.jpg);
}

body {
  display: grid;
  place-items: center;
  margin: 0;
  min-height: 100vh;
  background-color: hsl(222,50%,60%);
}

.outer {
  position: relative;
}

.card {
  width: 55vmin;
  height: 40vmin;
  background-image: var(--bg-img);
  background-size: 100% 100%;
  
  /* Make sure this element can exist in 3d space */
  transform-style: preserve-3d;
  
  transform:
    /* Set the point of view */
    perspective( calc( var(--perspective, 850) * 1px ) )
    /* Transform the element in all 3 dimensions */
    rotateX( calc( var(--rotaty-x) * 1deg ) )
    rotateY( calc( var(--rotaty-y) * 1deg ) )
    rotateZ( calc( var(--rotaty-z) * 1deg ) )
    /* Transform the element over the Z axis */
    translateZ( calc( var(--translate-z) * 1px ) );
}


.shadow {
  width: 55vmin;
  height: 40vmin;
  background-color: hsl(222,50%,30%);
  
  position: absolute;
  left: 0px;
  top: 0px;
  
  transform-style: preserve-3d;
  
  filter: blur( calc( var(--translate-z) * 0.1px ) );
  
  transform:
    perspective( calc( var(--perspective, 850) * 1px ) )
    rotateX( calc( var(--rotaty-x) * 1deg ) )
    rotateY( calc( var(--rotaty-y) * 1deg ) )
    rotateZ( calc( var(--rotaty-z) * 1deg ) )
}

.output {
  padding: 1rem 1.5rem 0rem 1.5rem;
  width: 250px;
  height: 150px;
  position: absolute;
  right: 10px;
  bottom: 10px;
  background-color: hsl(9,9%,0%,0.6);
  color: #efefef;
  border-radius: 5px;
}
const gui = new dat.GUI();

const transforms = {
  perspective: 1500,
  rotateX: 50,
  rotateY: 5,
  rotateZ: -40,
  translateZ: 20,
}

const outputBox = document.querySelector('.output pre');

const updateOutput = () => {
  
  let output = `transform-style: preserve-3d;
  
transform:
  perspective(${transforms.perspective}px)
  rotateX(${transforms.rotateX}deg)
  rotateY(${transforms.rotateY}deg)
  rotateZ(${transforms.rotateZ}deg)
  translateZ(${transforms.translateZ}px);`;
  
  outputBox.innerHTML = output;
}

updateOutput();

const updateProps = () => {
  document.documentElement.style.setProperty('--perspective', transforms.perspective);
  document.documentElement.style.setProperty('--rotaty-x', transforms.rotateX);
  document.documentElement.style.setProperty('--rotaty-y', transforms.rotateY);
  document.documentElement.style.setProperty('--rotaty-z', transforms.rotateZ);
  document.documentElement.style.setProperty('--translate-z', transforms.translateZ);
  
  updateOutput();
}

updateProps();

gui.add(transforms, 'perspective', 100, 2500, 100)
  .name('Perspective')
  .onChange(updateProps)

gui.add(transforms, 'rotateX', -360, 360, 1)
  .name('Rotate X')
  .onChange(updateProps)

gui.add(transforms, 'rotateY', -360, 360, 1)
  .name('Rotate Y')
  .onChange(updateProps)

gui.add(transforms, 'rotateZ', -360, 360, 1)
  .name('Rotate Z')
  .onChange(updateProps)

gui.add(transforms, 'translateZ', 1, 200, 1)
  .name('Translate Z')
  .onChange(updateProps)
  

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js