What is the best way to implement a sliding animation for a toggle button?

Currently, I am working on a toggle bar element that is functioning correctly in terms of styling the toggled button. However, I would like to add more animation to enhance the user experience.

The concept is to have the active button slide to the newly selected button for visual appeal. This means incorporating a sliding animation into the current code.

I am facing difficulty in figuring out how exactly to implement this feature. It seems that simply adding background and styles to the active element will not suffice; a floating or sliding box may be necessary.

While I prefer not to have someone implement it for me, I could use some guidance on where to start. Should I work with pseudo-elements? How can I ensure that the white button background element stretches to the width of the word behind it?

Although this is primarily a CSS-related question, I am unsure of how to initiate the implementation process.

If anyone has any advice, tips, or can point me in the right direction on how to achieve this effect, I would greatly appreciate it! Cheers!

Feel free to check out what I've built so far in CodeSandbox

Answer №1

To achieve a visually appealing effect of a white block moving behind text but in front of backgrounds, you can create a gap by using pseudo elements with lower z index to apply background colors onto elements.

By clicking on a button, you can calculate the distance the white block needs to move from the previously clicked button to reach the current one, as well as adjust its width accordingly.

In this code snippet, the 'white block' is actually represented by a pseudo element attached to the currently clicked button. This allows for easy determination of its final position directly under the active button.

const buttons = document.querySelectorAll('button');

function clicked(e) {
  const el = e.target;
  const prevEl = document.querySelector('button.animate');
  const x = (prevEl == null) ? '0%' : (prevEl.getBoundingClientRect().x - el.getBoundingClientRect().x) + 'px';
  const w2 = window.getComputedStyle(el).width;
  const w1 = (prevEl == null) ? 0 : window.getComputedStyle(prevEl).width;

  buttons.forEach(button => {
    button.classList.remove('animate');
  });
  el.style.setProperty('--x', x);
  el.style.setProperty('--w1', w1);
  el.style.setProperty('--w2', '100%');
  el.classList.add('animate');
}
buttons.forEach(button => {
    button.addEventListener('click', clicked);
  }

);
nav {
  display: inline-block;
  position: relative;
}

nav::before {
  content: '';
  position: absolute;
  background-color: gold;
  width: 100%;
  height: 100%;
  left: 0 top: 0;
  z-index: -3;
}

button {
  margin: 2vmin;
  background-color: transparent;
  position: relative;
}

button::before {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background-color: brown;
  z-index: -2;
}

button.animate::after {
  content: '';
  position: absolute;
  background-color: white;
  width: 100%;
  height: 100%;
  animation-name: move;
  animation-duration: 3s;
  animation-fill-mode: forwards;
  top: 0;
  left: 0;
  z-index: -1;
}

@keyframes move {
  0% {
    transform: translateX(var(--x));
    width: var(--w1);
  }
  100% {
    transform: translateX(0);
    width: var(--w2);
  }
}

@keyframes animate {
  0% {}
  100% {
    background-color: white;
  }
}
<nav>
  <button>AAAA</button>
  <button>AA</button>
  <button>AAAAAA</button>
  <button>A</button>
</nav>

Answer №2

If you're starting from scratch and want the flexibility to adjust the position of a white box in relation to a yellow box (using position: relative or absolute), one approach is to hardcode a function that takes the desired box coordinates. This function would then check if the white box is already in the correct place, and if not, move it x pixels in the right direction. The function could call itself recursively with a timeout, gradually moving the box closer to its target position.

This method essentially involves making small adjustments every few milliseconds until the white box reaches its final destination. By moving the box once every (1000/24)ms or less, the movement should appear smooth and fluid.

When it comes to determining the size of the box, you have the option to either hardcode the dimensions or create a function that calculates the appropriate size based on the text content provided.

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

When styled with an id, the DIV element does not inherit styles from a CSS class

I seem to be facing an issue with the code below, possibly due to using both class and id in the same div. Despite knowing they are meant to work together. For more information: Can I use DIV class and ID together in CSS? .PB { position: relative; ...

Using jQuery to move a div to a specific location on the page

Is there a way to translate the position of div x and y using Jquery that is compatible with all browsers, such as IE 7, IE8, IE9, and IE10? I have attempted the following: <div id="s1" style="-ms-transform:translate(159,430)"> hello ...

Adjust the class based on the model's value in AngularJS

items = {'apple', 'banana', 'lemon', 'cat', 'dog', 'monkey', 'tom', 'john', 'baby'} html <div class="variable" ng-repeat="item in items">{{item}} </div> ...

Connections between Wordpress websites and CSS styling

My inquiry consists of three parts: I am currently in the process of constructing a portfolio website using Wordpress, and I have encountered some peculiar links. For instance, on my about page, the link appears as localhost/AFolder/anotherfolder/ind ...

What is the best way to create an overscroll bounce effect for a list with a fixed height, even when the list items have not surpassed the height of the container?

When using a fixed-height ul with overflow scroll, the list will not have an overscroll bounce effect until its items exceed the height of the list. However, on mobile, I want the list container to have an overscroll bounce effect even when its items hav ...

Using CSS to rearrange the order of specific div elements with the nth-child() selector when targeting different

I am attempting to design a centered navbar for a webpage. The navbar consists of 5 divs and my goal is to have the third div become the first one when the screen size goes below 600px. Here is the HTML code: <div class="mainmenu"> < ...

Guide on implementing page styles to a polymer element

To apply styles from a 'normal' stylesheet to my polymer component, I included shim-shadowdom in the style and added /deep/ to the class. Here is an example: <html> <head> <style shim-shadowdom> .mylink /deep/ {col ...

Custom Bootstrap 3 Panel Organization

I'm intrigued by the layout shown in the image attached. My attempts to recreate it using a combination of columns and rows have been unsuccessful. Could it be that I'm going about this the wrong way? ...

Changing the Div Class in Master page from a Child page is a straightforward process that involves modifying

I am trying to dynamically change the style of a div element in the master page from my child page. This is the code I am using: protected void ShowMsgText(int MsgID) { HtmlGenericControl MsgInner; MsgInner = ((HtmlGenericControl) ...

Troubleshooting Vue2: Unable to assign a new value to a computed property - What could be causing this

I am facing an issue with a property called romanizationSystem_FK retrieved from an API, which sometimes contains a null value. My requirement is to set the value of this property to -1 whenever it is null. To implement this logic, I attempted using a com ...

Change the color of the icon from white to blue in png format using html/css

Changing a White Icon.png to a Blue Icon.png Using HTML/CSS The original icon.png is white in color. How can we change it to a blue color version using only HTML and CSS? HTML: <img src="icon.png" class="icon1"> CSS: .icon1 { background: url(ic ...

Troubleshooting error messages in Angular related to scss ModuleBuild

I've been working on applying a theme to my Angular application, but I've run into an issue. It seems that the src/theme.scss file I created is functioning correctly on its own. However, when I try to import "~@angular/material/theming", I encoun ...

Tips for retrieving the state value and using it as a parameter in methods

Is there a way to utilize Vuex state and access it in the methods property of components? I have a state called "currentThreadId" that I would like to use within my methods. The issue I am facing is being able to retrieve the "currentThreadId" from the Vu ...

Is there a way to fix the issue of ContextMenu not appearing at the right position within a scrollable

I have a div within an iframe that needs to display a context menu when right-clicked. The div's length may exceed the visible area, making it scrollable. However, the issue I am facing is that the context menu appears in a different position than whe ...

Utilizing React Material UI to divide the screen in half with one half being scrollable and the other half remaining fixed using UI Grid

My setup involves two Grid components, with one structured like this: <Grid container alignItems="stretch" spacing={3}> <Grid className="left-pane" item md={4} xs={12}> <Navigation /> </Grid> <Grid className="right-pan ...

Mastering Number Formatting in VueJS

While working with VueJS, I encountered difficulties in formatting numbers the way I wanted. After exploring options like the builtin currency filter and vue-numeric, I realized they required modifications to achieve the desired look. Furthermore, these so ...

Limiting the character input in ion-textarea within Ionic 2: A step-by-step guide

In my Ionic 2 application, I need to limit user comments to less than 500 characters in a text area. What is the best way to implement this restriction? ...

Guide on comparing an object against an array and retrieving a specific output

If I were to create a data structure like this: const carObj = {"1234":"Corvette","4321":"Subaru","8891":"Volvo"}; And also have an array that contains the IDs: const myArray = [1234, 4321, 8891, ...

Customize the style based on the state using styled components

I am currently working with a function component that looks like this: const Navbar = ({setNav, nav}) => { const [justify, setJustify] = useState('space-around') //get localStorage const user = JSON.parse(localStorage.getItem('user& ...

Navigation bar at the bottom using Twitter Bootstrap 3 that includes a combination of full-width and regular containers

I've been tasked with recreating the designer's layout using Bootstrap. The desired layout consists of two full-width bars and a fixed container for the main content and footer menu. I have successfully implemented this layout, including respons ...