<div class="phce card card-1">
  <div class="content">
      Paralex hover card effect
  </div>
</div>
<div class="phce card card-2">
  <div class="content">
      Paralex hover card effect
  </div>
</div>

// default setup Paralex Hover Card Effect (.phce)
.phce {
  perspective: 1000px;
  position: relative;

  .content{
    position: relative;
    overflow: hidden;
    transform-style: preserve-3d;

    &::before, &::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: -1;
      transform-style: preserve-3d;
    }
    &::before {
      background-image: var(--bg-image);
      background-size: cover;
    }
    &::after { 
      background: var(--bg-overlay, none);
    }
  }
  &:hover > .content::before{
    transform: scale(1.33) translateX(calc(-12.5% * var(--posX,0))) translateY(calc(-12.5% * var(--posY,0)));
  }
  // hover effects
  &:hover > .content { 
    transform: rotateX(calc(22.5deg * var(--posY,0))) rotateY(calc(-22.5deg * var(--posX,0))) 
  }
  &:not(:hover) > .content, &:not(:hover) > .content::before{
    transition: transform var(--transition-duration, 500ms) var(--transition-timing-function, linear)
  }
}

// custom styling
.card { width: min(30rem, 100%) }
.card-1{ --bg-image: url(https://picsum.photos/1920/1080?random=1) }
.card-2{ --bg-image: url(https://picsum.photos/1920/1080?random=2) }
.content{
  display: grid; 
  place-items: center;
  min-height: 16rem;
  padding: 2rem;
  border-radius: 1rem;
  font-family: system-ui, sans-serif;
  font-size: 2rem;
  color: white;
  --bg-overlay: rgb(0 0 0 / .5); 
}


// for demo 
* { margin: 0; padding: 0; box-sizing: border-box }

body { 
  display: grid; 
  place-items: center;
  gap: 2rem;
  padding: 2rem; 
  min-height: 100vh; 
  background-color: #1D1E22; 
}
View Compiled
const phceEls = document.querySelectorAll(".phce") || [];
phceEls.forEach(phceEl => phceEl.addEventListener("pointermove", phceSetPositions))

function phceSetPositions({ currentTarget: el, layerX: x, layerY: y }){
  const { width: w, height: h }  = el.getBoundingClientRect();
  el.style.setProperty("--posX", phceMapPositions(x, [0, w]));
  el.style.setProperty("--posY", phceMapPositions(y, [0, h]));   
}

function phceMapPositions (value, from, to=[-1,1], decimals=2) {
  const newValue = (value - from[0]) * (to[1] - to[0]) / (from[1] - from[0]) + to[0];
  const val = Math.min(Math.max(newValue, to[0]) , to[1]);
  return decimals && decimals > 0 ? Number(Math.round(val+'e'+decimals)+'e-'+decimals) : val;
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.