Transition the background image color smoothly from left to right in a seamless and continuous movement

A switch button located in the top right corner can toggle between light and dark modes. The background features a zoomed-in image.

Currently, the transition is as follows:

  • From left to right when switched to dark mode
  • From right to left when switched to light mode

However, I would like the transition to occur in only one direction. For instance, if it's in light mode and switched to dark mode, the background image should shift to the right (left > right) accordingly. And then, when switched back to light mode, the background image should move from left to right again (left > right).

Essentially, like a continuous loop controlled by a toggle button.

Is there a way to achieve this?

I'm thinking it may be possible with keyframes and animations, but I'm unsure. Is there a method to accomplish this using JavaScript without the necessity for keyframes?

Pay no mind to the code snippet below as it had to be extracted from my React project, so some CSS properties may appear unnecessary.

let Dark = false
const DarkOrLight = () => {
  const container = document.getElementsByClassName('Login-container')[0]
  if (!Dark) {
    container.style.backgroundPosition = 'right'
  } else {
    container.style.backgroundPosition = 'left'
  }
  Dark = !Dark
}
.toggle-container {
  position: fixed;
  top: 5px;
  right: 5%;
}

.toggle {
  appearance: none;
  width: 50px;
  height: 30px;
  background-image: linear-gradient(120deg, #383030 0%, #22282e 100%);
  cursor: pointer;
  border-radius: 20px;
}

.toggle:focus {
  outline: 0;
}

.toggle::after {
  content: '';
  background-image: linear-gradient(120deg, rgb(182, 244, 146), rgb(51, 139, 147));
  position: absolute;
  top: 5px;
  left: 5px;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  transition: all 1s ease;
}

.toggle:checked {
  background-color: #b6f492;
  background-image: linear-gradient(120deg, #b6f492, rgb(51, 139, 147));
}

.toggle:checked::after {
  transform: translateX(23px);
  background-image: linear-gradient(120deg, #383030 0%, #22282e 100%);
}

.Login-container {
  position: relative;
  background-image: linear-gradient(120deg, #b6f492, #338b93, #383030, #22282e);
  background-size: 400%;
  background-position: left;
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: end;
  transition: all 1s ease;
  font-family: Merriweather;
}
<div class="Login-container">
  <div class="toggle-container">
    <input class="toggle" type="checkbox" onClick=DarkOrLight()></input>
  </div>
</div>

Answer №1

Correcting Color Stops

  • You have set a background-size of 400%
  • However, you are only using 4 color-stops (instead of 5).

The issue arises when animating from left to right with your current code:

|left                          right|       bg-position moves left-to-right
|#1         |#2         |#3         |#4     4 colors-stops 
|0%      |100%    |200%    |300%    |400%   bg-size
| light  |     (anim)      |  dark  |       mode
|░░░░░░░░|▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒|▓▓▓▓▓▓▓▓|          

Do you know the exact color at 100%? No.
Do you know the exact color at 300%? No.
Notice the inconsistency? The color stops are off by one.

Here are some potential solutions:

  • Add one more color-stop -or
  • Reduce the width to 300% -or
  • Utilize CSS linear-gradient() stops at the desired % position

Recommendation

Animate a child element that has the desired background:

  • Width of 400%
  • 5 color-stops, with the last one matching the first!
|0%               |200%             |400%   animate left by -%
|#1      |#2      |#3      |#4      |#1     5 colors-stops 
|0%      |100%    |200%    |300%    |400%   width
| light  | (anim) |  dark  | (anim) |       mode 
|░░░░░░░░|▒▒▒▒▒▒▒▒|▓▓▓▓▓▓▓▓|▒▒▒▒▒▒▒▒|░░...

At 400%, we return to color #1 - ideal for the loop logic! And by "animate left by -%", I imply animating the GPU accelerated transform: translateX() property value.

...

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

Experiencing a hiccup while attempting to query the Twitter API using Node.js

I am a beginner exploring the world of node.js, but I keep encountering a perplexing "write after end" error. Despite searching for solutions online, none seem to address my specific issue. My current project involves querying the Twitter API. req.on(&apo ...

Guidelines for leveraging AngularJS Decorators to deactivate a button within an Html document

Currently, I am utilizing the blur admin theme and exploring the possibility of using decorators to hide a button without directly modifying the HTML. Despite my efforts, I have been unable to successfully conceal the button. Can someone provide guidance o ...

Steps for refreshing a JavaScript function responsible for generating a table

Within the code snippet provided, there is a click event attached to a table row. Upon clicking a row, the script extracts the id value from the first column and triggers a REST call. Subsequently, a new table is constructed using a third-party function ca ...

Creating a network of communication between API routes in NextJS

Can the fetch API be used within an API route in NextJs? I have a large handler and instead of having everything in one handler, I'd like to modularize it so that after completing a specific task (e.g., writing to a database), I can call another handl ...

Struggling to center a modal at the exact middle of the page using Bootstrap 5

My navigation bar has a button that, when clicked, triggers a modal to appear at the top of the page. I am trying to center it horizontally. Here is the HTML code: </button> <!-- </button> --> <div class="text-dark "> < ...

"Convert a date string to a date object using the verbose moment date

I utilized the materialize datepicker to select a date in French format. Now I need to convert this formatted date back to a date object for use in my API. Here's how I attempted to revert the date to a standard format: moment("dimanche 30 juillet 20 ...

What is the process for updating selenium-webdriver if it is not globally installed on my system?

After installing selenium-webdriver with the command npm install selenium-webdriver (without the -g option), I found that the usual instruction of running webdriver-manager update did not work since it was installed locally. What is the correct way to upd ...

Issue encountered while trying to modify the color of a placeholder

Whenever I attempt to modify the placeholder's color: ::-webkit-input-placeholder { /* WebKit, Blink, Edge */ color: #909; } :-moz-placeholder { /* Mozilla Firefox 4 to 18 */ color: #909; opacity: 1; } : ...

What is the best way to reach a link using Selenium?

Challenge : Unable to interact with a link using JavaScript through Selenium. Attempted Solutions: element = driver.find_element_by_css_selector(a {href: "javascript:void(0)"}) resulted in a SyntaxError. element = driver.execute_script("ja ...

Rendering color with a three.js image texture (loaded using ColladaLoader)

I just started learning three.js 2 days ago and I'm a bit of a newbie. After drawing a box on SketchUp, exporting it as a collada file (.dae), and loading it into a scene with three.js, I tried tiling the object with textures but unfortunately, I fai ...

Incorporating a protected Grafana dashboard into a web application

I am looking to incorporate Grafana into my web application using AngularJS. The main objective is to allow users to access the Grafana UI by clicking on a button within my application. Setting up an apache reverse proxy for Grafana and ensuring proper COR ...

Refreshing the page causes the Angular/Ionic Singleton instance to be destroyed

I have a TypeScript singleton class that is responsible for storing the login credentials of a user. When I set these credentials on the login page and navigate to the next page using Angular Router.navigate (without passing any parameters), everything wor ...

Cookie-powered JavaScript timer ceases after 60 seconds

I'm having an issue with my countdown timer where it stops counting after just one minute. It seems to pause at 54:00 when I set it for 55 minutes, and at 1:00 when I set it for 2 minutes. Any suggestions on how I can resolve this and make it continue ...

Backbone and Laravel - Choose a squad and automatically create users for the selected team

I've recently started exploring backbone.js and have gone through Jeffery Way's tutorial on using Laravel and Backbone. As of now, I have a list of teams being displayed along with their ids fetched from the database. I have also set up an event ...

Create a circular div that fills in when hovered over using CSS

I attempted to create an interesting effect when hovering over a circular div, but I struggled to figure out how to fill it in with the same round shape. Currently, the fill is in a square shape, but I am looking to have it match the shape of the div (whi ...

What is the best way to pass an array as a parameter in Angular?

I have set up my routing module like this: const routes: Routes = [ { path: "engineering/:branches", component: BranchesTabsComponent }, { path: "humanities/:branches", component: BranchesTabsComponent }, ]; In the main-contin ...

Enliven the character limit reaction by incorporating a thrilling shake animation when it reaches

I have implemented a feature in my component where if a user reaches the character limit, the component should shake. However, despite my efforts, the shaking effect is not working in the current code. const useStyles = makeStyles(() => ({ shake ...

Conceal the Angular Material toolbar (top navigation bar) automatically when scrolling downwards

In my Angular application, the main navigation consists of a standard toolbar positioned at the top of the page. My goal is to have this navigation bar smoothly scroll up with the user as they scroll down, and then reappear when they scroll back up. I at ...

Sorry, the account with the number 0 on the rinkeby network is invalid due to the private key being shorter than the expected 32

Attempting to launch my dapp on the rinkeby test network using the following command: npx hardhat run scripts/deploy.js --network rinkeby However, whenever I try to deploy the contract, I encounter an error stating that the private key size is too short ...

Retrieve information from an ajax call within an Angular application

I need assistance with 2 requests I have. $.ajax({ type: "POST", url: "http://sandbox.gasvisor.com:9988/uaa/oauth/token", data: "grant_type=client_credentials", headers: { 'Content-Type': 'application/x-www-form-urlencoded&a ...