Shifting a div from side to side

I don't have much experience with coding, so I was hoping for some assistance.

My goal was to create a div that moves back and forth using toggleClass;

$('div').on('click', function() {
    $(this).toggleClass('active');
});

as well as keyframes;

.active {
    animation-name: moveme;
    animation-duration: 1s;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
}

@keyframes moveme {
    0%  {transform: translate(0,0)}
    50%  {transform: translate(-200px, 0px)}
    100%  {transform: translate(-200px,-50px);}
}

However, when the div returns to its original position, it does not animate. I would like the div to animate in reverse with the same animation. Is there a way to achieve this?

You can view what I'm attempting to do here jsfiddle.net/jmrMW/43/ The example is simple now, but it will become more complex in the future.

Thank you kindly for your help! ^^

Answer №1

When it comes to manipulating classes in Javascript, the effects can be instant. However, if your CSS animations are only bound to the .active class, clicking a second time can cause you to lose that class and therefore lose the animation effect.

Instead of duplicating code like others have suggested, let's think like true programmers and utilize the power of CSS3 animations. Why not try a different approach by setting animation-direction: alternate and animation-play-state: paused, then defining a CSS class for movement:

.moving {
  animation-play-state: running;
}

Next, apply this class to the element for just 1 second after it has been clicked:

var $moveable = $( '.moveable' ).eq( 0 );

$moveable.click(function() {
    $moveable.addClass( 'moving' );
    setTimeout(function() {
         $moveable.removeClass( 'moving' );
    }, 1000);
});

Take a look at this fiddle for a demo.

Update

This solution does have a drawback - using timers in both JS and CSS may not sync perfectly. The animation becomes infinite, going slightly further each cycle. To fix this, we can increment animation-iteration-count to prevent it from proceeding to the next cycle. Still fun experimenting though!

Check out this updated fiddle for more details.

Answer №2

I have created a modified version of your JSFiddle code. I essentially replicated the keyframes you already had but implemented them in reverse for a different effect. Feel free to check it out!

$('div').on('click', function() {
  if ( $(this).hasClass("go-up") ) {
    $(this).removeClass("go-up").addClass("go-down");
  } else {
    $(this).addClass("go-up").removeClass("go-down');
  }
});
div{
  background:#aaa;
  width: 200px;
  margin: 20vh auto;
  height: 200px;
}
.go-up {
  animation-name: moveup;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-delay: 0s;
  animation-fill-mode: forwards;
}
.go-down {
  animation-name: movedown;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-delay: 0s;
  animation-fill-mode: forwards;
}

@keyframes moveup {
  0%  {transform: translate(0,0)}
  50%  {transform: translate(-100px, 0px)}
  100%  {transform: translate(-100px,-50px);}
}

@keyframes movedown {
  0%  {transform: translate(-100px,-50px);}
  50%  {transform: translate(-100px, 0px)}
  100%  {transform: translate(0,0)}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div></div>

Check out the modified version 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

How to easily transfer a JSON file to a server using Vue and Node.js

As a newcomer to the world of Node.js and Vue development, my goal is to establish a seamless process for users to create and upload a JSON file to the server when they save data in a form. This process should occur effortlessly in the background, allowing ...

What could be the reason for receiving an HttpErrorResponse when making a GET request that returns byte data

When using these headers, the API returns byte data as a response. let headers = { headers: new HttpHeaders({ 'Content-Type': 'application/octet-stream', 'responseType':'arraybuffer' as 'js ...

Leveraging dependency injection in Angular 2+ with pre-loaded models

I desire the ability to create an instance of a model using a constructor while also providing injected services to that model. To clarify, I envision something like this: var book = new Book({ id: 5 }); // creates instance, sets id = 5 book.makeHttpCa ...

Incorporating an SVG with CSS styling from a stylesheet

After exploring various articles and questions on the topic, I am yet to find a definitive solution. I have an external file named icon.svg, and my objective is to utilize it across multiple HTML files with different fill colors and sizes for each instanc ...

Background color for the DIV is not displaying properly when it is set to the

While trying to set the background color of a div to light blue #2390bb, I encountered an issue. Even though I have already set the body background color to Light Grey#D6D6D6, the light blue color doesn't display in the div. Can anyone help me figure ...

Expand Menu Options (jQuery)

Currently facing a jQuery problem that I can't seem to figure out. I've set up a menu with submenu elements and want to toggle the content height by clicking on menu items. The issue arises when clicking on another item causes the content to coll ...

How is it that cross-domain scripting is able to occur with local files on a smartphone or tablet?

My Experiment: To test cross-site scripting (XSS), I set up an index.html file with a xss.js script that utilized the jQuery.get() function. After opening the index.html in various browsers (Firefox, Chrome, IE, and Opera), I attempted to trigger an ajax ...

Angular 4 - The Promising Outcome: How to Retrieve the Value upon Completion

Is there a way to retrieve a value from a promise and store it in a global variable? I've been attempting to accomplish this, but the global variable remains undefined. import { Injectable } from '@angular/core'; import {ActivatedRouteSnap ...

Utilize Vue.js methods to reverse the string within a paragraph using the appropriate function

Hello everyone, I've been attempting to implement a function to reverse a string within a paragraph text in vue.js. I've created a method called reverseword to reverse the words and added it to a card using :rule="reverseword()", but un ...

Reduce XSLTProcessor output by 50%

I have a persistent problem (from my perspective, at least). Every time I use XSLTProcessor.transformToFragment, the output is consistently halved compared to the input. For example, when I receive 200 entries in an XML file as a response from a webservi ...

I am having trouble getting my textarea to accept width attributes

Strangely, the text area on my website just won't cooperate with the width I specify. I've double-checked the CSS multiple times to no avail! Take a look at this jsfiddle example that demonstrates what I'm trying to achieve. However, on my ...

Choose the currently active md-tab within the md-dialog's md-tab-group

I need to create a dynamic md-dialog with an md-tab-group that has two tabs. The md-dialog should open based on the button clicked, displaying the corresponding tab content. The initial template where the md-dialog is triggered: <button md-button class ...

Re-sequence a contiguous array by mapping and filtering its elements

Within my React code, I have a list component that utilizes array.map to display a list of items. The list items have alternating backgrounds; every other item's background color is determined by whether the id field from the data structure is even o ...

Instructions on deactivating the background when the sidebar is displayed and closing the sidebar by clicking anywhere other than the sidebar

I'm in the process of creating a sidebar for my website. When the sidebar is displayed (by clicking showRight), I want to disable the background content so that the user can't interact with anything outside of the menu. If the user clicks on th ...

Leveraging multer for handling a FormData object in a node.js server

Having trouble with an HTML form that includes two buttons among other text input areas. The front-end javascript code is set up to handle the submit action by creating a FormData object to store the file and sending it via a jQuery AJAX request to a node. ...

Angular utilizes ZoneAwarePromise rather than a plain String output

I expected the giver code to return a string, but it is returning ZoneAwarePromise. Within the service: getCoveredPeriod() { let loanDetails = this.getLoanDetails().toPromise(); loanDetails.then((res: any) => { const coveredPeriodStart ...

Tips for ensuring only one dropdown is opened at a time

Hey there! I've been struggling with getting my dropdowns to open one at a time on my website. I attempted to hide them all by default, but they still insist on opening simultaneously. Any ideas on what I might be overlooking? Thank you for your help! ...

The identical items combined into a single array

I have a specific data structure that I am struggling to manipulate in JavaScript. The goal is to merge objects with the same invoice_nr into one array, while keeping other objects in separate arrays. const result = [ { invoice_nr: 16, order_id: ...

Navigate the user to various pages in a Node.js application based on login status

Looking for guidance on a login system within my application? I need to redirect users based on their roles. Below is the code for the login controller, along with node.js snippets and the login HTML page. Any help would be appreciated. Login.html - < ...

When we typically scroll down the page, the next section should automatically bring us back to the top of the page

When we scroll down the page, the next section should automatically bring us back to the top of the page without having to use the mouse wheel. .bg1 { background-color: #C5876F; height: 1000px; } .bg2 { background-color: #7882BB; height: 1000px; } .bg3 ...