skip to Main Content

I’m trying to animate letters so they fly in from random positions using JavaScript. The animation works perfectly when the letters are directly inside the .container class. However, when I move the letters inside a <button> element, the animations no longer work as expected—the letters appear in the center instead of flying in from random positions.

I suspect the issue might be related to how the button affects the layout or positioning of the letters. How can I fix this and keep the letters inside the button without breaking the animation?

Here’s my code:

const letters = document.querySelectorAll('.letter');

function animateLetters() {
  letters.forEach((letter, index) => {
    const randomX = (Math.random() - 0.5) * window.innerWidth; // Random X
    const randomY = (Math.random() - 0.5) * window.innerHeight; // Random Y

    letter.style.setProperty('--random-x', `${randomX}px`);
    letter.style.setProperty('--random-y', `${randomY}px`);

    letter.style.animationDelay = `${index * 0.2}s`;
  });
}

animateLetters();
body {
  background-color: #282c34;
  color: #fff;
  font-family: Arial, sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  overflow: hidden;
}

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  font-size: 2rem;
  font-weight: bold;
  text-align: center;
  position: relative;
}

.letter {
  position: relative;
  opacity: 0;
  animation: flyIn 1.5s ease forwards;
}

@keyframes flyIn {
  from {
    opacity: 0;
    transform: translate(var(--random-x), var(--random-y));
  }

  to {
    opacity: 1;
    transform: translate(0, 0);
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Letter Animation</title>

</head>

<body>
  <div class="container">
    <button class="button"> <!-- the problem here when I add the letters inside this button-->
      <span class="letter">L</span>
      <span class="letter">e</span>
      <span class="letter">t</span>
      <span class="letter">'</span>
      <span class="letter">s</span>
      <span class="letter">&nbsp;</span>
      <span class="letter">o</span>
      <span class="letter">r</span>
      <span class="letter">g</span>
      <span class="letter">a</span>
      <span class="letter">n</span>
      <span class="letter">i</span>
      <span class="letter">z</span>
      <span class="letter">e</span>
      <span class="letter">&nbsp;</span>
      <span class="letter">e</span>
      <span class="letter">v</span>
      <span class="letter">e</span>
      <span class="letter">r</span>
      <span class="letter">y</span>
      <span class="letter">t</span>
      <span class="letter">h</span>
      <span class="letter">i</span>
      <span class="letter">n</span>
      <span class="letter">g</span>
    </button>
  </div>

</body>

</html>

2

Answers


  1. The issue you’re encountering is likely due to the fact that a <button> element has some default styles applied by the browser (like display: inline-block, padding, borders, etc.), which could affect the layout of the letters inside it. Since the letter spans are relatively positioned, they might be constrained by the boundaries of the <button> and not able to move freely within the window.

    Solution:

    You can fix this by adjusting the positioning of the <button> and its contents. Specifically, you want to ensure the button behaves like a block element and has no padding or borders that might interfere with the animation.

    Here’s how you can adjust your code:

    1. Make the <button> behave like a block-level element, ensuring that the spans inside it are not restricted.
    2. Remove any unnecessary padding, borders, or other styles that might restrict the position of the letters.

    Updated CSS:

    body {
      background-color: #282c34;
      color: #fff;
      font-family: Arial, sans-serif;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      overflow: hidden;
    }
    
    .container {
      display: flex;
      flex-wrap: wrap;
      gap: 5px;
      font-size: 2rem;
      font-weight: bold;
      text-align: center;
      position: relative;
    }
    
    button.button {
      display: block; /* Make button block level */
      background: transparent; /* Remove background */
      border: none; /* Remove border */
      padding: 0; /* Remove padding */
      cursor: pointer; /* Make it clickable */
      position: relative; /* Allow absolute positioning inside */
    }
    
    .letter {
      position: absolute; /* Absolute positioning allows letters to move freely */
      opacity: 0;
      animation: flyIn 1.5s ease forwards;
    }
    
    @keyframes flyIn {
      from {
        opacity: 0;
        transform: translate(var(--random-x), var(--random-y));
      }
    
      to {
        opacity: 1;
        transform: translate(0, 0);
      }
    }
    

    Updated HTML (No changes needed here):

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Letter Animation</title>
    </head>
    <body>
      <div class="container">
        <button class="button">
          <span class="letter">L</span>
          <span class="letter">e</span>
          <span class="letter">t</span>
          <span class="letter">'</span>
          <span class="letter">s</span>
          <span class="letter">&nbsp;</span>
          <span class="letter">o</span>
          <span class="letter">r</span>
          <span class="letter">g</span>
          <span class="letter">a</span>
          <span class="letter">n</span>
          <span class="letter">i</span>
          <span class="letter">z</span>
          <span class="letter">e</span>
          <span class="letter">&nbsp;</span>
          <span class="letter">e</span>
          <span class="letter">v</span>
          <span class="letter">e</span>
          <span class="letter">r</span>
          <span class="letter">y</span>
          <span class="letter">t</span>
          <span class="letter">h</span>
          <span class="letter">i</span>
          <span class="letter">n</span>
          <span class="letter">g</span>
        </button>
      </div>
    </body>
    </html>
    

    Key Changes:

    1. Positioning: The .letter spans are now absolutely positioned, which allows them to move freely inside the <button> element.
    2. Button styles: By setting display: block, border: none, and padding: 0, the button no longer affects the positioning of the letter spans, and the animation should work as expected.

    This should resolve the issue and allow your letter animation to function correctly inside the <button>.

    Login or Signup to reply.
  2. I simply added , button.button to the CSS and made the background less dark #282c3420; to illustrate better.

    const letters = document.querySelectorAll('.letter');
    
    function animateLetters() {
      letters.forEach((letter, index) => {
        const randomX = (Math.random() - 0.5) * window.innerWidth;
        const randomY = (Math.random() - 0.5) * window.innerHeight;
        letter.style.setProperty('--random-x', `${randomX}px`);
        letter.style.setProperty('--random-y', `${randomY}px`);
        letter.style.animationDelay = `${index * 0.2}s`;
      });
    }
    
    animateLetters();
    body {
      background-color: #282c3420;
      color: #fff;
      font-family: Arial, sans-serif;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      overflow: hidden;
    }
    
    .container,
    button.button {
      display: flex;
      flex-wrap: wrap;
      gap: 5px;
      font-size: 2rem;
      font-weight: bold;
      text-align: center;
      position: relative;
    }
    
    .letter {
      position: relative;
      opacity: 0;
      animation: flyIn 1.5s ease forwards;
    }
    
    @keyframes flyIn {
      from {
        opacity: 0;
        transform: translate(var(--random-x), var(--random-y));
      }
    
      to {
        opacity: 1;
        transform: translate(0, 0);
      }
    }
    <body>
      <div class="container">
        <button class="button">
          <span class="letter">L</span>
          <span class="letter">e</span>
          <span class="letter">t</span>
          <span class="letter">'</span>
          <span class="letter">s</span>
          <span class="letter">&nbsp;</span>
          <span class="letter">o</span>
          <span class="letter">r</span>
          <span class="letter">g</span>
          <span class="letter">a</span>
          <span class="letter">n</span>
          <span class="letter">i</span>
          <span class="letter">z</span>
          <span class="letter">e</span>
          <span class="letter">&nbsp;</span>
          <span class="letter">e</span>
          <span class="letter">v</span>
          <span class="letter">e</span>
          <span class="letter">r</span>
          <span class="letter">y</span>
          <span class="letter">t</span>
          <span class="letter">h</span>
          <span class="letter">i</span>
          <span class="letter">n</span>
          <span class="letter">g</span>
        </button>
      </div>
    </body>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search