skip to Main Content

I am trying to set up an animation where, on hover, an arrow within my circular button animates out of the button to the right and then comes back in from the left. It would start animating slowly to the right and speed up while leaving the boundary of the circle and then it would re-enter from the left and slow down as it reaches the starting point again. I was able to set up some keyframes to mostly accomplish this, but it is not very smooth when it re-enters from the left.

button {
  display: inline-flex;
  width:50px;
  height:50px;
  align-items:center;
  justify-content:center;
  border-radius:50px;
  border:none;
  -webkit-appearance:none;
  appearance:none;
  position:relative;
  overflow:hidden;
}

button img {
  display:block;
  width:30px;
}

button:hover img {
  animation: train;
  animation-duration: 3s;
  animation-timing-function: cubic-bezier(0.785, 0.135, 0.06, 1.01);
}

@keyframes train {
    50% {
        transform: translateX(calc(100% + 30px));
    }
    50.001% {
        transform: translateX(-100%);
    }
    100% {
        transform:translateX(0);
    }
}
<button><img alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjIuODggMTA4LjA2IiB4bWxuczp2PSJodHRwczovL3ZlY3RhLmlvL25hbm8iPjxwYXRoIGQ9Ik01OC45NCAyNC4yOGExNC4yNyAxNC4yNyAwIDAgMSAyMC4zNS0yMGwzOS40OSA0MC4xNmExNC4yOCAxNC4yOCAwIDAgMSAwIDIwbC0zOC42OSAzOS4zNWExNC4yNyAxNC4yNyAwIDEgMS0yMC4zNS0yMGwxNS4wOC0xNS4zOC02MC42Ny0uMjlhMTQuMjcgMTQuMjcgMCAwIDEgLjI0LTI4LjU0bDU5Ljg1LjI4LTE1LjMtMTUuNTh6Ii8+PC9zdmc+" /></button>

2

Answers


  1. calc(100% + 30px)

    Maybe you simply forgot to apply this at 50.001%?

    50.001% {
        transform: translateX(calc( (100% + 30px) * -1) );
    }
    
    Login or Signup to reply.
  2. You have to use half the sum of both width (50px + 30px)/2 = 40px to make sure your element fully exit its container. Also note that 100% in translate refers to the arrow width, not the button width.

    button {
      display: inline-grid;
      width: 50px;
      aspect-ratio: 1;
      place-items: center;
      border-radius: 50%;
      border: none;
      appearance: none;
      overflow: hidden;
    }
    
    button img {
      display: block;
      width: 30px;
    }
    
    button:hover img {
      animation: train 3s cubic-bezier(0.785, 0.135, 0.06, 1.01);
    }
    
    @keyframes train {
      50% {
        translate:  40px;
      }
      50.1% {
        translate: -40px;
      }
    }
    <button><img alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjIuODggMTA4LjA2IiB4bWxuczp2PSJodHRwczovL3ZlY3RhLmlvL25hbm8iPjxwYXRoIGQ9Ik01OC45NCAyNC4yOGExNC4yNyAxNC4yNyAwIDAgMSAyMC4zNS0yMGwzOS40OSA0MC4xNmExNC4yOCAxNC4yOCAwIDAgMSAwIDIwbC0zOC42OSAzOS4zNWExNC4yNyAxNC4yNyAwIDEgMS0yMC4zNS0yMGwxNS4wOC0xNS4zOC02MC42Ny0uMjlhMTQuMjcgMTQuMjcgMCAwIDEgLjI0LTI4LjU0bDU5Ljg1LjI4LTE1LjMtMTUuNTh6Ii8+PC9zdmc+" /></button>

    To avoid pixel values, express the width in percentage and update the code like below:

    button {
      display: inline-grid;
      width: 50px;
      aspect-ratio: 1;
      place-items: center;
      border-radius: 50%;
      border: none;
      padding: 0;
      appearance: none;
      overflow: hidden;
    }
    
    button img {
      display: block;
      width: 60%;
    }
    
    button:hover img {
      animation: train 3s cubic-bezier(0.785, 0.135, 0.06, 1.01);
    }
    
    @keyframes train {
      50% {
        translate: calc( 50%*(1 + 1/.6)); /* .6 = 60% */
      }
      50.1% {
        translate: calc(-50%*(1 + 1/.6));
      }
    }
    <button><img alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjIuODggMTA4LjA2IiB4bWxuczp2PSJodHRwczovL3ZlY3RhLmlvL25hbm8iPjxwYXRoIGQ9Ik01OC45NCAyNC4yOGExNC4yNyAxNC4yNyAwIDAgMSAyMC4zNS0yMGwzOS40OSA0MC4xNmExNC4yOCAxNC4yOCAwIDAgMSAwIDIwbC0zOC42OSAzOS4zNWExNC4yNyAxNC4yNyAwIDEgMS0yMC4zNS0yMGwxNS4wOC0xNS4zOC02MC42Ny0uMjlhMTQuMjcgMTQuMjcgMCAwIDEgLjI0LTI4LjU0bDU5Ljg1LjI4LTE1LjMtMTUuNTh6Ii8+PC9zdmc+" /></button>
    
    <button style="width: 100px"><img alt="" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjIuODggMTA4LjA2IiB4bWxuczp2PSJodHRwczovL3ZlY3RhLmlvL25hbm8iPjxwYXRoIGQ9Ik01OC45NCAyNC4yOGExNC4yNyAxNC4yNyAwIDAgMSAyMC4zNS0yMGwzOS40OSA0MC4xNmExNC4yOCAxNC4yOCAwIDAgMSAwIDIwbC0zOC42OSAzOS4zNWExNC4yNyAxNC4yNyAwIDEgMS0yMC4zNS0yMGwxNS4wOC0xNS4zOC02MC42Ny0uMjlhMTQuMjcgMTQuMjcgMCAwIDEgLjI0LTI4LjU0bDU5Ljg1LjI4LTE1LjMtMTUuNTh6Ii8+PC9zdmc+" /></button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search