How to ensure that a div is always centered when another one disappears after an animation?

Viewed 54

(CSB for reference)

I have a button comprised of an icon and some text. When the button is hovered, the text moves to the right, and so does the icon. It creates a nice animation

enter image description here

The problem is I make this transition happen with the following code:

.button:not(.disabled):hover .icon {
  transform: translate3d(150%, 0, 0);
}

The 150% is just an arbitrary value, if you go inside App.js and change the width of the icon (line 10), you can tell that it's no longer centered. I can't wrap my head around a solution that would ensure the following (my goals):

  • When the button is not hovered, both the icon and the text should be center.
  • When the button is hovered, only the icon should be ultimately centered.

Would appreciate any guidance.

2 Answers

First give your button a fixed width.

.button {
  width: 130px;
}

and then you just need to set the position of your icon class to absolute on button hover.

.button:not(.disabled):hover .icon {
  position: absolute;
}

Perfectly-smooth solution that works for every situation:

body {
  display: grid;
  place-items: center;
  gap: 1em;
}

button {
  --gap: 5px;
  
  font-size: 14px;
  padding: .3em .7em;
  background: none;
  border: 2px solid black;
  border-radius: 4px;
  cursor: pointer;
  overflow: hidden;
}

button > div {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  white-space: nowrap;
  gap: var(--gap);
  transition: .3s ease-out;
}

button > div > i {
  flex: 0;
  transition: inherit;
}

button > div > span { 
  flex: 1;
  transition: inherit;
}

button:hover > div {
  width: calc(200% + var(--gap));
}

button:hover > div > i {
  flex: 1;
  color: crimson;
}

button:hover > div > span {
  opacity: 0;
}
<button>
  <div>
    <i>♥️</i>
    <span>Short</span>
  </div>
</button>

<button>
  <div>
    <i>♥️</i>
    <span>Normal label</span>
  </div>
</button>

<button>
  <div>
    <i>♥️</i>
    <span>Very long label text example</span>
  </div>
</button>

Codepen demo

Related