CSS3 transition applied to a jQuery direction-aware hover effect

I'm encountering difficulties making direction-aware hover and css transitions function correctly. Specifically, I am attempting to create a grid of elements with front and back faces, and on hover, have a css transition that flips the element to display the back face.

Here's an example of the transition (without direction-aware): fiddle

Currently, no matter how your mouse enters an element, it always flips up. My goal is to have it flip in the direction the mouse enters or exits.

Examples:

Below is my attempt at implementing direction-aware: fiddle

I am using jQuery to add classes related to the mouse's direction in/out.

.hover-in-top {}
.hover-in-right {}
.hover-in-bottom {}
.hover-in-left {}

.hover-out-top {}
.hover-out-right {}
.hover-out-bottom {}
.hover-out-left {}

While the direction-aware example somewhat works, there are significant glitches that I can't seem to figure out. (I've been overthinking this and my brain feels overloaded.)

I hope this explanation makes sense. Thank you.

Answer №1

I have made some adjustments to your query.

After modifying a few transitions, I switched them to animations

$('.box-container .box').each(function() {
    $(this).on('mouseenter mouseleave', function(e) {
        var $this = $(this),
            width = $this.width(),
            height = $this.height();

        var x = (e.pageX - $this.offset().left - (width / 2)) * (width > height ? (height / width) : 1),
            y = (e.pageY - $this.offset().top - (height / 2)) * (height > width ? (width / height) : 1);

        // top = 0, right = 1, bottom = 2, left = 3
        var dir_num = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4,
            directions = ['top', 'right', 'bottom', 'left'];

        // If mouse enter
        if (e.type === 'mouseenter') {
            // Remove all hover out classes
            $this.removeClass(function(index, css) {
                return (css.match(/(^|\s)hover-out-\S+/g) || []).join(' ');
            });

            // Add in direction class
            $this.addClass('hover-in-' + directions[dir_num]);
        }


        // If mouse leave
        if (e.type === 'mouseleave') {
            // Remove all hover in classes
            $this.removeClass(function(index, css) {
                return (css.match(/(^|\s)hover-in-\S+/g) || []).join(' ');
            });

            // Add out direction class
            $this.addClass('hover-out-' + directions[dir_num]);
        }
    });
});
* {
    box-sizing: border-box;
}

.box-container {
    padding: 20px;
    width: 600px;
}
.box-container:after {
    content: '';
    display: block;
    clear: both;
}
.box-container .box {
    float: left;
    width: 50%;
    height: 200px;
    position: relative;
    perspective: 600px;
    border: 1px solid transparent;
}
.box-container .box .front, .box-container .box .back {
    float: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    backface-visibility: hidden;
    transition: all 1s ease-in-out;
    color: white;
    font-size: 60px;
}
.box-container .box .front {
    background: blue;
    transform: rotateX(0) rotateY(0);
    z-index: 900;
}
.box-container .box .back {
    background: red;
    z-index: 800;
}
.box-container .box:hover .front {
    z-index: 900;
}
.box-container .box:hover .back {
    z-index: 1000;
    transform: rotateX(180) rotateY(0);
}

.box-container .box.hover-in-top .front,
.box-container .box.hover-out-bottom .back {
    transform: rotateX(-179deg) rotateY(0);
}
.box-container .box.hover-in-top .back,
.box-container .box.hover-out-bottom .front {
    animation: Xminus 1s ease-in-out;
}
@keyframes Xminus {
    from {transform: rotateX(179deg) rotateY(0);}
    to   {transform: rotateX(  0deg) rotateY(0);}
}

.box-container .box.hover-in-bottom .front,
.box-container .box.hover-out-top .back {
    transform: rotateX(179deg);
}
.box-container .box.hover-in-bottom .back,
.box-container .box.hover-out-top .front {
    animation: Xplus 1s ease-in-out;
}
@keyframes Xplus {
    from {transform: rotateX(-179deg) rotateY(0);}
    to   {transform: rotateX(   0deg) rotateY(0);}
}

.box-container .box.hover-in-right .front,
.box-container .box.hover-out-left .back {
    transform: rotateY(-179deg);
}
.box-container .box.hover-in-right .back,
.box-container .box.hover-out-left .front {
    animation: Yminus 1s ease-in-out;
}
@keyframes Yminus {
    from {transform: rotateX(0deg) rotateY(179deg);}
    to   {transform: rotateX(0deg) rotateY(  0deg);}
}

.box-container .box.hover-in-left .front,
.box-container .box.hover-out-right .back {
    transform: rotateY(179deg);
}

.box-container .box.hover-in-left .back,
.box-container .box.hover-out-right .front {
    animation: Yplus 1s ease-in-out;
}
@keyframes Yplus {
    from {transform: rotateX(0deg) rotateY(-179deg);}
    to   {transform: rotateX(0deg) rotateY(  0deg);}
}
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box-container">
    <div class="box">
        <div class="front">FRONT</div>
        <div class="back">BACK</div>
    </div>
    <div class="box">
        <div class="front">FRONT</div>
        <div class="back">BACK</div>
    </div>
    <div class="box">
        <div class="front">FRONT</div>
        <div class="back">BACK</div>
    </div>
    <div class="box">
        <div class="front">FRONT</div>
        <div class="back">BACK</div>
    </div>
</div>

The drawback of using animations is that the animation may be disrupted if you move away from the div before it completes

However, if you move slowly and remain on the divs until the animation finishes, it should function properly.

I am optimistic that someone will discover a more effective solution

Answer №2

In my opinion, avoiding CSS transitions is the most effective approach to solving this problem.

By incorporating jQuery's animate function and leveraging its animations queue feature, you can easily achieve synchronized animations for a seamless user experience.

I have made adjustments to your code example to demonstrate how to animate the transition using JavaScript instead of CSS.

Check out the updated code snippet here.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

HTML animation effect on subpage with a URL modification [LATEST UPDATE]

Can you smoothly load a new subpage in the background, update the URL, and fade it in while an animation is playing on the previous page? Check out this example (jsFiddle) to see a simple animation: $(document).ready(function() { 'use strict&apo ...

Transforming an Excel document into JSON format: inspection of JSON code structure

Looking to transform Excel data into JSON format, but unsure if the current structure will be ideal for processing with D3.js. Planning to incorporate this JSON file within D3.js for visualization purposes. Here's a snippet of the Excel file: In the ...

In CSS, use the p tag to make sure content fills the available space when the browser is resized beyond a certain point

Before I begin, I must clarify that I do not specialize in front-end development and my expertise in UI/UX is limited. With that said, here is my query: I have a div containing p tags. I wish for this div to have a width: 700px when the browser window is ...

Is it possible to locate and eliminate the apostrophe along with the preceding letter?

My objective is to tidy up a character string by removing elements that are not essential for the user and SEO, specifically the (letter before the apostrophes) in this case. I am looking for a regex solution or explanation of how to achieve this in PHP, a ...

Implementing the Delete feature using AJAX in this specific scenario: What is the best approach?

My website utilizes PHP, Smarty, MySQL, jQuery, and other technologies. It involves fetching a large amount of data from the database and presenting matching question ids on a webpage. This process of retrieving and displaying the matching question ids for ...

How to align two <select> elements side by side using Bootstrap

The issue I am encountering is that these two select elements within the same control-group are being displayed vertically when I want them to be displayed horizontally. I attempted using inline-block in CSS, but there are other <div> elements with ...

Retrieve the text label from the parent option group

Below is the HTML code snippet: <select id="categoryg"> <optgroup label="Main" value="binding"> <optgroup label="Sub" value="binding"> <option value="46&quo ...

retrieve information in json format from a specified web address

I need to figure out why the data from a specific URL is not being displayed properly on my node application. It seems like there might be an error in my code. const extractRefDefaultSchema = async (data) => { const url = "https://mos.esante.gouv.f ...

Certain hyperlinks are refusing to open within an embedded iframe

I'm currently facing an issue with finding a solution for a simple problem. I am in the process of developing a portfolio plugin and one of the requirements is to showcase projects within an iframe to demonstrate their responsive layout. However, I&ap ...

No internet connection detected - please check your connection and try again

In the scenario where the internet connection is not available, when the user clicks a button, an error message should be displayed using a dialog box. I attempted to use navigator.online in my Android mobile webview but it did not work. How can I show t ...

What is the advantage of not importing related modules?

As a newcomer to React, please excuse any novice questions I may have. I am currently utilizing npx create-react-app to develop a React app, but I'm unsure of the inner workings: Q1-If I were to throw an error in a component like so: import React, { ...

Having trouble with the @keyup event not functioning properly in Vue?

I'm attempting to trigger a method when the enter key is pressed, but for some reason it's not working. Here's the code snippet: <template> <div> <button @click="callEvent" @keyup.enter="callEvent"> Click </button ...

The generation of React Native Jest coverage results may vary depending on how an ES6 module is exported

I am working with a React Native button component that consists of its own index.js and styles.js files. The content of styles.js is as follows: import { StyleSheet } from "react-native"; export default StyleSheet.create({ container: { borderRadius ...

Top approach for inserting Class instance into a group

I need some guidance on how to approach this issue. I am interested in creating a set of objects similar to the example below: Person P = new Person(); P.Name = 'John'; P.Surname = 'Dough'; var People = []; People.push(P); Can this b ...

Update the CSS styling of a parent div based on the active state of specific child divs

I have a class with 4 distinct columns. div class="mainContent"> <div class="left-Col-1" *ngIf="data-1"> </div> <div class="left-Col-2" *ngIf="!data-1"> ...

Is there a way to use jQuery to eliminate divs that contain multiple identical data values?

Is there a way to accomplish this? <div class="chat_timestamp_group" data-date="08-March-2016"></div> <div class="chat_timestamp_group" data-date="08-March-2016"></div> <div class="chat_timestamp_group" data-date="14-March-2016" ...

What is the reasoning behind the repetitive use of @media (max-width: 767px) in the Twitter Bootstrap

Why is the media query @media (max-width: 767px) repeated in the bootstrap-responsive.css file? To find out, you can view the file by visiting ...

Stop the css animation from playing

I created a slideshow using HTML and CSS, and I'm looking to implement a feature where the slideshow pauses when my mouse hovers over it. I attempted to achieve this by using -webkit-animation-play-state: paused;, but unfortunately, it only pauses one ...

Angular toolbar on the left side that hovers seamlessly

1 I am using Angular Material toolbar and trying to position a span inside the toolbar on the left side. I have attempted using CSS float left, but it is not working. Can anyone provide some assistance please? <mat-toolbar> <span>le ...

Expanding the height of Bootstrap 4 cards

I'm having an issue with Bootstrap 4's card columns where the height of the shorter card ends up stretching to match the one beside it. This only occurs when I add the 'row' class to the parent div. If I remove the 'row' class ...