Toggling reverses multiple CSS keyframe animations

I've been working on a unique animation to switch my website between dark and light mode. The animation is quite complex, so I anticipate that the solution will be equally intricate.

Currently, I am toggling between classes, but this approach makes it difficult for me to reverse the animation when switching the button. I have searched for simple solutions online, but unfortunately, I haven't come across any that provide a clear explanation on how to reverse the animation with multiple CSS keyframes.

Below is the CSS section of the code, which is essentially repeated 8 times:

.line {
width: 1rem;
height: 2rem;
background-color: black;
position: absolute;
display: block;
transform: translateY(5rem);
border-radius: 0.5em;
}
.is-dark {
animation: is-dark 2s forwards;
}
@keyframes is-dark {
    0% {
        height: 2rem;
        width: 1rem;
        border-radius: 0.5em;
        transform: translateX(0) translateY(5rem);
    }
    33.33% {
        height: 1rem;
        width: 1rem;
        border-radius: 50%;
        transform: translateX(0) translateY(5rem);
    }
    66.66% {
        height: 3rem;
        width: 3rem;
        border-radius: 50%;
        transform: translateX(0) translateY(0);
    }
    100% {
        height: 3rem;
        width: 3rem;
        border-radius: 50%;
        transform: translateX(1rem) translateY(-1rem);
    }
}

JS

let line = document.querySelector(".line");

let btn = document.querySelector(".btn");

btn.addEventListener("click", toggleDarkMode);

function toggleDarkMode() {
  line.classList.toggle("is-dark");
}

For the complete version of this button, you can visit: https://jsfiddle.net/a6euokxy/4/

Thank you in advance, Luk Ramon

Answer №1

I have devised a solution for the issue you are facing. I have made improvements to the JavaScript file by adding classes with animation properties like alternate infinite paused;. These classes with animation have also been incorporated into the HTML.

Check out the working example with the use of LocalStorage.

let theme = 'light';
// Get all container elements
const lines = document.querySelector('.container').querySelectorAll('div');

let btn = document.querySelector('.btn');

btn.addEventListener('click', toggleDarkMode);

function toggleDarkMode() {
  if (theme === 'light') {
    lines.forEach(line => {
      // Remove unnecessary DOM elements
      if (!line.hasAttribute('class')) return;
      // Set pause after play 2s animation
      setTimeout(() => {
        line.removeAttribute('style');
      }, 2000);
      // Start play
      line.setAttribute('style', 'animation-play-state: running');
    });
    theme = 'dark';
    return;
  }

  if (theme === 'dark') {
    lines.forEach(line => {
      if (!line.hasAttribute('class')) return;

      setTimeout(() => {
        line.removeAttribute('style');
      }, 2000);

      line.setAttribute('style', 'animation-play-state: running');
    });
    theme = 'light';
    return;
  }
}
* {
  padding: 0;
  margin: 0;
}

.button {
  display: flex;
  justify-content: center;
  margin-top: 3rem;
}

.button .btn {
  background: none;
  border: 0.2rem solid black;
  font-size: 1rem;
  padding: 1rem;
  border-radius: 2rem;
  font-weight: bold;
}

.container {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

#circle {
  width: 4rem;
  height: 4rem;
...
  opacity: 0;
  }
}
<div class="button">
  <button class="btn">Dark Mode</button>
</div>
<div class="container">
  <div id="circle"></div>
  <div id="lines">
    <div class="line is-dark"></div>
    <div class="line1 is-dark1"></div>
    <div class="line2 is-dark2"></div>
    <div class="line3 is-dark3"></div>
  </div>
  <div id="lines1">
    <div class="line4 is-dark4"></div>
    <div class="line5 is-dark5"></div>
    <div class="line6 is-dark6"></div>
    <div class="line7 is-dark7"></div>
  </div>
</div>

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

Managing Angular Directives Through Controllers

My Angular directive functions as a login popup, opening a popup page when triggered. modal = angular.module('Directive.Modal',[]); modal.directive('modalLogin',function() { return { restrict: 'EA', scope ...

Navigating to an AngularJS state through an email hyperlink

Trying to guide users from an email link to a specific state within my Angular app presents a challenge due to its single page nature, making direct URL redirection impossible. Past attempts involved utilizing URL parameters: The email includes this link ...

Is it possible to use JavaScript to toggle the visibility of the date picker when using the HTML5 input type=date?

Looking to personalize the HTML5 input type="date" element by integrating a separate button that triggers the visibility of the date picker dropdown. Struggling to find any information on this customization. Any assistance would be greatly valued! ...

JavaScript error: "null or not an object" bug

I have implemented the JavaScript code below to display horizontal scrolling text on the banner of my website. Surprisingly, it works perfectly fine on one server but throws an error on another server with the message: Error: 'this.mqo' is nul ...

Display content in a div after the page is fully loaded with either a placeholder or animated loading

Hello everyone, this is my first post on here. I am relatively new to PHP, so any help or advice would be greatly appreciated. ...

Is there a necessity for me to utilize the nodejs https module if my hosting service offers TLS Certificates?

As a first-time application deployer for real-life use, I am utilizing the Stripe API for payment handling. My plan is to deploy the Node.js application on Render host, which promises fully managed and free TLS certificates for all hosted applications an ...

Breadcrumb navigation that is determined by data hierarchies and relationships between parent and child items

I am looking to implement a dynamic breadcrumb system on my website using data-driven methodology. The necessary data is stored in a MariaDB database and has the following structure: parent_id | parent_name | child_id | child_name ——————— ...

Achieving full opacity text within a semi-transparent div: a simple guide

Within my div, I have an a tag. I applied opacity:0.5 to the div, causing the text inside to also appear at 0.5 opacity. I am looking for a way to have the text display with opacity:1 inside my div that has an overall opacity of 0.5, without resorting to ...

What is the process of transforming a string into a JSON object?

var str = '""{""as"":""N9K-93180YC-EX""}""'; I attempted to remove the extra quotes using a regular expression: var str1 = str.replace(/\"/g, ""); After removing the extra quotes, the string now looks like "{as:N9K-93180YC-EX}". However, ...

Utilizing doT.js for Organizing Nested Lists from Arrays and Objects

Can nested lists be generated with doT.js? My current code only processes the first object in the array (g1) and ignores the rest. Is there a solution for this using doT.js? The desired result should be: G1 T11 T12 T13 G2 T21 T22 T23 $(document) ...

The functionality for bold and italics does not seem to be functioning properly in either Firefox

Text formatted with <b></b> and <i></i> tags appears correctly on iPhone and Internet Explorer, but lacks formatting in Firefox or Chrome. I have included the .css files below. Additionally, I attempted to add i { font-style:italic ...

Incorporating Javascript into a <script> tag within PHP - a step-by-step guide

I am trying to integrate the following code into a PHP file: if (contains($current_url, $bad_urls_2)) { echo '<script> $('body :not(script,sup)').contents().filter(function() { return this.nodeType === 3; ...

Reposition the span element to the right of the div tag

I need help adjusting the positioning of the elements in this HTML code. How can I move the span element with the image to the right of the div tag? Here is the code snippet: <div style='width:600px;padding-top: 2px;padding-bottom: 1px'& ...

Navigation menu elements out of place

I am facing some challenges while trying to create a horizontal navigation: The first element appears to be displaced Is there a better way to position the text centered below the icon? Currently, I have used a tag for this purpose. Also, how can I us ...

The ng-click event in AngularJS does not function as expected when nested within another ng-repeat loop

I am facing an issue with ng-click in my Angular application (version 1.0.4). The first ng-click works fine, but the second one does not. <div class="menu-group" ng-repeat="module in modules"> <div ng-click="toggle($event, $parent)" ...

Angular 6 - Share content easily on mobile devices (IOS, Android)

After reviewing this example detailing the use of Angular 5 for copying to clipboard, I encountered issues when trying to run it on the iPhone 6s. Is there a more comprehensive solution available? ...

Building numerous pagination features in a single page using Codeigniter

I'm just starting out with codeigniter and I need help creating multiple paginations on one page. I've tried it, but only one pagination is working while the others are giving me errors. Can someone please assist me? I read some suggestions that ...

Having trouble with creating SQLite tables using JavaScript within a for loop

I have developed a multi-platform app using AngularJS, JavaScript, Phonegap/Cordova, Monaca, and Onsen UI. In order to enable offline usage of the app, I have integrated an SQLite Database to store various data. After conducting some basic tests, I confir ...

What is the best way to showcase distinct sections from several web pages on a single webpage?

I want to showcase multiple web pages on a single page using Iframes. What is the best way to achieve this and display them all together? ...

When using react, it is not possible to have a <span> element as a child of a <

I designed a custom select dropdown feature for use in a redux-form within a react-redux application. The dropdown functions well, with no performance issues, but I am encountering a warning in the browser. Warning: validateDOMNesting(...): <span> c ...