BACK TO RESOURCES
Forest Paths
Discover uncharted paths
Deep Woods
Embrace the quietude
High Peaks
Reach new heights

Cards with a relational 3D hover effect

Markup
<div class="dan_3d_cards-container">
    
    <!-- Card 1 -->
    <div class="dan_3d_wrap">
      <div class="dan_3d_card-shadow"></div>
      <div class="dan_3d_card dan_3d_card-1">
        <div class="dan_3d_card-front">
          <div class="dan_3d_card-title">Forest Paths</div>
          <div class="dan_3d_card-subtitle">Discover uncharted paths</div>
          <div class="dan_3d_card-shine"></div>
        </div>
      </div>
    </div>

    <!-- Card 2 -->
    <div class="dan_3d_wrap">
      <div class="dan_3d_card-shadow"></div>
      <div class="dan_3d_card dan_3d_card-2">
        <div class="dan_3d_card-front">
          <div class="dan_3d_card-title">Deep Woods</div>
          <div class="dan_3d_card-subtitle">Embrace the quietude</div>
          <div class="dan_3d_card-shine"></div>
        </div>
      </div>
    </div>

    <!-- Card 3 -->
    <div class="dan_3d_wrap">
      <div class="dan_3d_card-shadow"></div>
      <div class="dan_3d_card dan_3d_card-3">
        <div class="dan_3d_card-front">
          <div class="dan_3d_card-title">High Peaks</div>
          <div class="dan_3d_card-subtitle">Reach new heights</div>
          <div class="dan_3d_card-shine"></div>
        </div>
      </div>
    </div>

  </div>
CSS
<style>
    /* Container for layout and global perspective context */
    .dan_3d_cards-container {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 50px;
      flex-wrap: wrap;
      min-height: 100vh;
      width: 100%;
      padding: 50px;
      box-sizing: border-box;
      perspective: 1000px;
    }

    /* Standard wrapper for each card */
    .dan_3d_wrap {
      position: relative;
      width: 300px;
      height: 450px;
      perspective: 600px;
    }

    .dan_3d_card-shadow, .dan_3d_card {
      width: 100%;
      height: 100%;
      position: absolute;
      top: 0;
      left: 0;
      border-radius: 10px;
      transform-style: preserve-3d;
    }

    .dan_3d_card {
      z-index: 1;
      transform-style: preserve-3d;
    }

    /* Unique backgrounds for the three cards */
    .dan_3d_card-1 {
      background: #fff url("https://images.unsplash.com/photo-1441716844725-09cedc13a4e7?fit=crop&fm=jpg&h=950&q=80&w=1925") 50% 50%;
      background-size: 200%;
    }

    .dan_3d_card-2 {
      background: #fff url("https://images.unsplash.com/photo-1447752875215-b2761acb3c5d?fit=crop&fm=jpg&h=950&q=80&w=1925") 50% 50%;
      background-size: 200%;
    }

    .dan_3d_card-3 {
      background: #fff url("https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?fit=crop&fm=jpg&h=950&q=80&w=1925") 50% 50%;
      background-size: 200%;
    }

    .dan_3d_card-shine {
      position: absolute;
      width: 100%;
      height: 100%;
      transform-style: preserve-3d;
      z-index: 1;
      border-radius: 10px;
      background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 60%);
      z-index: -1;
    }

    .dan_3d_card-shadow {
      top: 10px;
      z-index: -1;
      background: #B3B3B3;
      box-shadow: 0 0 30px 10px #aaa;
      transform: scale(0.9) translateZ(-40px);
    }

    .dan_3d_card-front, .dan_3d_card-title, .dan_3d_card-subtitle {
      position: absolute;
      color: #FFF;
      transform-style: preserve-3d;
    }

    .dan_3d_card-front {
      border-radius: 10px;
      width: 100%;
      height: 100%;
      z-index: 0;
      background-color: rgba(0, 0, 0, 0.1);
    }

    .dan_3d_card-title {
      font-weight: 700;
      text-align: left;
      left: 30px;
      bottom: 140px;
      font-size: 35px;
      line-height: 30px;
      text-shadow: 0 5px 8px rgba(0, 0, 0, 0.65);
      transform: translateZ(40px);
      overflow: hidden;
      margin: 0;
      width: 80%;
    }

    .dan_3d_card-subtitle {
      font-weight: normal;
      text-align: left;
      left: 30px;
      width: 80%;
      bottom: 80px;
      font-size: 25px;
      line-height: 20px;
      text-shadow: 0 3px 6px rgba(0, 0, 0, 0.8);
      transform: translateZ(60px);
    }
</style>
JS
<script>
        $(document).mousemove(function(event) {
      var mouseX = event.pageX;
      var mouseY = event.pageY;
      var wHeight = $(window).height();
      var wWidth = $(window).width();

      $('.dan_3d_wrap').each(function() {
        var $wrap = $(this);
        var $card = $wrap.find('.dan_3d_card');
        var $cardTitle = $wrap.find('.dan_3d_card-title');
        var $cardSubtitle = $wrap.find('.dan_3d_card-subtitle');
        var $cardShine = $wrap.find('.dan_3d_card-shine');
        var $cardShadow = $wrap.find('.dan_3d_card-shadow');

        // Calculate card's current center relative to the document
        var offset = $wrap.offset();
        var cardCenterX = offset.left + ($wrap.width() / 2);
        var cardCenterY = offset.top + ($wrap.height() / 2);

        // Calculate the vector offset from the card's center to the cursor
        var dx = mouseX - cardCenterX;
        var dy = mouseY - cardCenterY;

        // Reference range scales
        var refWidth = wWidth / 2;
        var refHeight = wHeight / 2;

        var percentX = dx / refWidth;   
        var percentY = dy / refHeight;  

        // Card rotation values
        var around1 = -1 * (percentY * 12) + 'deg'; 
        var around2 = (percentX * 12) + 'deg';

        // Translation/sliding displacement
        var trans1 = (percentX * 15) + 'px';
        var trans2 = (percentY * 15) + 'px';

        // Dynamic shine gradient calculations
        var theta = Math.atan2(dy, dx);
        var angle = theta * 180 / Math.PI - 90;
        
        // Dynamic opacity based on mouse distance to card center
        var dist = Math.sqrt(dx * dx + dy * dy);
        var maxDist = Math.sqrt(refWidth * refWidth + refHeight * refHeight);
        var opacity = Math.min(0.7, Math.max(0.1, (1 - (dist / maxDist)) * 0.7));

        // Background parallax glide
        var bgPosX = 50 + (percentX * 10);
        var bgPosY = 50 + (percentY * 10);

        // Apply shine
        $cardShine.css('background', 'linear-gradient(' + angle + 'deg, rgba(255,255,255,' + opacity + ') 0%, rgba(255,255,255,0) 80%)');

        // Apply card positioning and tilt transformations
        $card.css({
          "transform": "translate3d(" + trans1 + ", " + trans2 + ", 0) rotateX(" + around1 + ") rotateY(" + around2 + ")",
          "background-position": bgPosX + "% " + bgPosY + "%"
        });

        // Apply shadow translations
        var shadowX = (dx * -0.02) + 12;
        var shadowY = (dy * -0.02) + 12;
        var shadowRotY = (dx / 25) * 0.5;
        var shadowRotX = (dy / -25);

        $cardShadow.css({
          "transform": "scale(0.9) translateX(" + shadowX + "px) translateY(" + shadowY + "px) rotateY(" + shadowRotY + "deg) rotateX(" + shadowRotX + "deg)"
        });

        // Apply title 3D layer translation
        var titleX = (dx / 25) * 0.7;
        var titleY = (dy / 25) * 1.65;
        $cardTitle.css({
          "transform": "translateX(" + titleX + "px) translateY(" + titleY + "px) translateZ(40px)"
        });

        // Apply subtitle 3D layer translation
        var subtitleX = (dx / 25) * 0.5;
        var subtitleY = (dy / 25) * 1.15;
        $cardSubtitle.css({
          "transform": "translateX(" + subtitleX + "px) translateY(" + subtitleY + "px) translateZ(60px)"
        });
      });
    });
</script>