You are currently viewing Better Interactive Directional Hover Cards –  Elementor Tutorial

Better Interactive Directional Hover Cards – Elementor Tutorial

(This page includes affiliate links. If you click and purchase, I receive a small commission at no extra cost from you and that way you can support me. I only recommend tools that I have personally used and loved.)

Tutorial Video:

Introduction – Directional Aware Hover Cards

In this tutorial, we will create hover effect for your cards that rotate in the direction of your cursor when entered.

Hover Me

Check Elementor Templates

DMmotionarts

Add Any Widgets

Like and Subscribe

Hover Card

Directional Aware Hover Code

  1. We only need 2 CSS classes for our 2 divs/containers.
  2. dm-direction-card : CSS class of our card containers / divs.
  3. dm-direction-inner-card : CSS class of our inner card container/ div that shows on hover. This container needs to be inside dm-direction-card container / div.
  4. For more 3D effect, you can increase the perspective but make sure to also increase the out animations degree from 100 to more.
  5. All animatons take .3s , you can increase or decrease it your liking.
				
					<style>
    
.dm-direction-card {
    position: relative;
    overflow: hidden;
    perspective: 1000px;
}

.dm-direction-inner-card {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
    backface-visibility: hidden;

    /* Hidden by default */
    transform: rotateX(90deg);
}

/* ---------- ENTER ---------- */

.in-top .dm-direction-inner-card {
    transform-origin: 50% 0%;
    animation: in-top .3s ease forwards;
}

.in-right .dm-direction-inner-card {
    transform-origin: 100% 50%;
    animation: in-right .3s ease forwards;
}

.in-bottom .dm-direction-inner-card {
    transform-origin: 50% 100%;
    animation: in-bottom .3s ease forwards;
}

.in-left .dm-direction-inner-card {
    transform-origin: 0% 50%;
    animation: in-left .3s ease forwards;
}

/* ---------- EXIT ---------- */

.out-top .dm-direction-inner-card {
    transform-origin: 50% 0%;
    animation: out-top .3s ease forwards;
}

.out-right .dm-direction-inner-card {
    transform-origin: 100% 50%;
    animation: out-right .3s ease forwards;
}

.out-bottom .dm-direction-inner-card {
    transform-origin: 50% 100%;
    animation: out-bottom .3s ease forwards;
}

.out-left .dm-direction-inner-card {
    transform-origin: 0% 50%;
    animation: out-left .3s ease forwards;
}

/* ---------- KEYFRAMES ---------- */

@keyframes in-top {
    from { transform: rotateX(-90deg); }
    to   { transform: rotateX(0deg); }
}

@keyframes in-right {
    from { transform: rotateY(-90deg); }
    to   { transform: rotateY(0deg); }
}

@keyframes in-bottom {
    from { transform: rotateX(90deg); }
    to   { transform: rotateX(0deg); }
}

@keyframes in-left {
    from { transform: rotateY(90deg); }
    to   { transform: rotateY(0deg); }
}

@keyframes out-top {
    from { transform: rotateX(0deg); }
    to   { transform: rotateX(-100deg); }
}

@keyframes out-right {
    from { transform: rotateY(0deg); }
    to   { transform: rotateY(-100deg); }
}

@keyframes out-bottom {
    from { transform: rotateX(0deg); }
    to   { transform: rotateX(100deg); }
}

@keyframes out-left {
    from { transform: rotateY(0deg); }
    to   { transform: rotateY(100deg); }
}
    
</style>

<script>

document.addEventListener("DOMContentLoaded", (event) => {        
    
const cards = document.querySelectorAll(".dm-direction-card");

const classes = [
    "in-top", "in-right", "in-bottom", "in-left",
    "out-top", "out-right", "out-bottom", "out-left"
];

function getDirection(e, element) {

    const rect = element.getBoundingClientRect();

    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;

    const distances = {
        top: y,
        right: rect.width - x,
        bottom: rect.height - y,
        left: x
    };

    let direction = "top";
    let smallest = Infinity;

    for (const side in distances) {
        if (distances[side] < smallest) {
            smallest = distances[side];
            direction = side;
        }
    }

    return direction;
}

cards.forEach(card => {

    card.addEventListener("mouseenter", e => {

        card.classList.remove(...classes);

        // Restart animation
        void card.offsetWidth;

        card.classList.add("in-" + getDirection(e, card));
    });

    card.addEventListener("mouseleave", e => {

        card.classList.remove(...classes);

        // Restart animation
        void card.offsetWidth;

        card.classList.add("out-" + getDirection(e, card));
    });

});

});
</script>
				
			

Leave a Reply