Search code examples
htmlcssmenucss-animations

How to activate animation when mouse left the div/space?


So I was making the site that has menu that "slides" down from the top. This is css code for aniamtion;

@keyframes slide-vertical-44-px-down {
    0%{height: 0px;}
    100%{height: 44px;}
}

I got it to work but i don't know how to make it come back to its original height when mouse leaves menu bar.

* {
  margin: 0px;
}

@font-face {
  font-family: ground;
  src: url(Blackground-z88Bl.otf);
}

.top {
  font-family: Helvetica;
  height: 50px;
  position: fixed;
  width: 100%;
}

.top:hover {
  height: 100px
}

#cool-lookin-box {
  /*aniamcja*/
  animation-name: slide-vertical-50-px;
  animation-duration: 400ms;
  animation-fill-mode: forwards;
  /**/
  background-color: rgb(68, 68, 68);
  overflow: hidden;
  white-space: nowrap;
  font-size: 40px;
  font-family: ground;
  color: white;
  display: block;
  padding: 5px;
}

@keyframes slide-vertical-50-px {
  0% {
    height: 0px;
  }
  100% {
    height: 50px;
  }
}

@keyframes slide-vertical-44-px-down {
  0% {
    height: 0px;
  }
  100% {
    height: 44px;
  }
}

@keyframes slide-vertical-44-px-up {
  100% {
    height: 44px;
  }
  0% {
    height: 0px;
  }
}

.top:hover .menu {
  display: flex;
  animation: slide-vertical-44-px-up 200ms forwards;
  overflow: hidden;
  white-space: nowrap;
  box-shadow: 10px 10px 20px rgb(83, 83, 83);
}

.menu {
  display: none;
  justify-content: center;
  background-color: rgb(128, 128, 128);
  cursor: pointer;
  animation: slide-vertical-44-px-up 200ms forwards;
}

.menu #menu-bar li {
  color: whitesmoke;
  display: inline-block;
  padding: 10px;
  align-items: center;
  font-size: 20px;
  transition: 400ms;
}

.menu #menu-bar li:hover {
  background-color: rgb(175, 175, 175);
  border-radius: 5px;
  color: rgb(65, 65, 65);
}

#test {
  height: 1000px;
  background-color: rgb(0, 0, 0);
}
<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="style.css">
  <script src="code.js"></script>
</head>

<body>
  <div class="top">
    <div id="cool-lookin-box">
      <p>TESTOWY TEXT</p>
    </div>
    <div class="menu">
      <ul id="menu-bar">
        <li>First</li>
        <li>Second</li>
        <li>Third</li>
        <li>Fourth</li>
        <a href="https://google.com">
          <li>Fifth</li>
        </a>
      </ul>
    </div>
  </div>
  <div id="test"></div>
</body>

</html>

I've tried doing it with transitions but it doesn't work. I also tried doing it with another animation but it doesn't work either. I would be really thankful if somebody would help me with this.


Solution

  • Explanation

    Animating height with CSS is a nightmare, if you have to use the "magic number" method. This also seems to be something you could accomplish more easily with transitions rather than animations.

    The main reason I recommend transitions for this case, is because a hover will run a transition and the un-hovering will just run the transition in reverse, without the need for specifying a separate animation.

    In the case you want to do something more than reversing a transition, then you should use an animation.

    So now to tackle the height issue… Instead of using height, I'd recommend using either a transform with translateY and/or scaleY, or—my personal favorite option—grid-template-rows.

    Examples

    Using Transition

    With Transform

    * {
      margin: 0px;
      /* Helps with stacking context, but could be applied to essential elements only */
      position: relative;
    }
    
    @font-face {
      font-family: ground;
      src: url(Blackground-z88Bl.otf);
    }
    
    .top {
      font-family: Helvetica;
      height: 50px;
      position: fixed;
      width: 100%;
      /* Keeps it on top of everything */
      z-index: 20;
    }
    
    #cool-lookin-box {
      /*aniamcja*/
      animation-name: slide-vertical-50-px;
      animation-duration: 400ms;
      animation-fill-mode: forwards;
      /**/
      background-color: rgb(68, 68, 68);
      overflow: hidden;
      white-space: nowrap;
      font-size: 40px;
      font-family: ground;
      color: white;
      display: block;
      padding: 5px;
      /* Make sure menu is hidden when collapsed */
      z-index: 10;
    }
    
    .top:hover .menu,
    .menu:hover {
      /* display: flex; (not necessary) */
      overflow: hidden;
      white-space: nowrap;
      box-shadow: 10px 10px 20px rgb(83, 83, 83);
      /* Transform End */
      transform: translateY(0);
    }
    
    .menu {
      display: flex; /* Changed to flex, as "none" cannot be eased yet */
      justify-content: center;
      background-color: rgb(128, 128, 128);
      cursor: pointer;
      /* Transition */
      transition: transform 200ms ease;
      /* Transform Start */
      transform: translateY(-100%);
    }
    
    .menu #menu-bar li {
      color: whitesmoke;
      display: inline-block;
      padding: 10px;
      align-items: center;
      font-size: 20px;
      transition: background-color 400ms ease;
    }
    
    .menu #menu-bar li:hover {
      background-color: rgb(175, 175, 175);
      border-radius: 5px;
      color: rgb(65, 65, 65);
    }
    
    #test {
      height: 1000px;
      background-color: rgb(0, 0, 0);
      color: white;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <link rel="stylesheet" href="style.css">
      <script src="code.js"></script>
    </head>
    
    <body>
      <div class="top">
        <div id="cool-lookin-box">
          <p>TESTOWY TEXT</p>
        </div>
        <div class="menu">
          <ul id="menu-bar">
            <li>First</li>
            <li>Second</li>
            <li>Third</li>
            <li>Fourth</li>
            <a href="https://google.com">
              <li>Fifth</li>
            </a>
          </ul>
        </div>
      </div>
      <div id="test"></div>
    </body>
    
    </html>

    With Grid Template Rows

    * {
      margin: 0px;
      /* Helps with stacking context, but could be applied to essential elements only */
      position: relative;
    }
    
    @font-face {
      font-family: ground;
      src: url(Blackground-z88Bl.otf);
    }
    
    .top {
      font-family: Helvetica;
      height: 50px;
      position: fixed;
      width: 100%;
      /* Keeps it on top of everything */
      z-index: 20;
    }
    
    #cool-lookin-box {
      /*aniamcja*/
      animation-name: slide-vertical-50-px;
      animation-duration: 400ms;
      animation-fill-mode: forwards;
      /**/
      background-color: rgb(68, 68, 68);
      overflow: hidden;
      white-space: nowrap;
      font-size: 40px;
      font-family: ground;
      color: white;
      display: block;
      padding: 5px;
    }
    
    .top:hover .menu,
    .menu:hover {
      /* display: flex; (not necessary) */
      overflow: hidden;
      white-space: nowrap;
      box-shadow: 10px 10px 20px rgb(83, 83, 83);
      /* Grid Template Rows End */
      grid-template-rows: 1fr;
    }
    
    .menu {
      display: grid; /* Changed to grid */
      justify-content: center;
      background-color: rgb(128, 128, 128);
      cursor: pointer;
      /* Transition */
      transition: grid-template-rows 200ms ease;
      /* Grid Template Rows Start */
      grid-template-rows: 0fr;
    }
    
    /* Necessary to collapse with grid-template-rows */
    #menu-bar {
      overflow-y: hidden;
    }
    
    .menu #menu-bar li {
      color: whitesmoke;
      display: inline-block;
      padding: 10px;
      align-items: center;
      font-size: 20px;
      transition: background-color 400ms ease;
    }
    
    .menu #menu-bar li:hover {
      background-color: rgb(175, 175, 175);
      border-radius: 5px;
      color: rgb(65, 65, 65);
    }
    
    #test {
      height: 1000px;
      background-color: rgb(0, 0, 0);
      color: white;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <link rel="stylesheet" href="style.css">
      <script src="code.js"></script>
    </head>
    
    <body>
      <div class="top">
        <div id="cool-lookin-box">
          <p>TESTOWY TEXT</p>
        </div>
        <div class="menu">
          <ul id="menu-bar">
            <li>First</li>
            <li>Second</li>
            <li>Third</li>
            <li>Fourth</li>
            <a href="https://google.com">
              <li>Fifth</li>
            </a>
          </ul>
        </div>
      </div>
      <div id="test"></div>
    </body>
    
    </html>

    Using Animation

    * {
      margin: 0px;
      /* Helps with stacking context, but could be applied to essential elements only */
      position: relative;
    }
    
    @font-face {
      font-family: ground;
      src: url(Blackground-z88Bl.otf);
    }
    
    .top {
      font-family: Helvetica;
      height: 50px;
      position: fixed;
      width: 100%;
      /* Keeps it on top of everything */
      z-index: 20;
    }
    
    #cool-lookin-box {
      /*aniamcja*/
      animation-name: slide-vertical-50-px;
      animation-duration: 400ms;
      animation-fill-mode: forwards;
      /**/
      background-color: rgb(68, 68, 68);
      overflow: hidden;
      white-space: nowrap;
      font-size: 40px;
      font-family: ground;
      color: white;
      display: block;
      padding: 5px;
      /* Makes sure menu is hidden when collapsed */
      z-index: 10;
    }
    
    .top:hover .menu,
    .menu:hover {
      /* display: flex; (not necessary) */
      overflow: hidden;
      white-space: nowrap;
      box-shadow: 10px 10px 20px rgb(83, 83, 83);
      /* Open Animation */
      animation: open-menu 500ms ease;
      transform: translateX(0);
      grid-template-rows: 1fr;
    }
    
    .menu {
      display: grid; /* Changed to grid */
      justify-content: center;
      background-color: rgb(128, 128, 128);
      cursor: pointer;
      /* Close Animation */
      animation: close-menu 200ms ease;
      transform: translateX(100%);
      grid-template-rows: 0fr;
    }
    
    @keyframes open-menu {
      from {
        transform: translateX(100%);
        grid-template-rows: 1fr;
      }
      to {
        transform: translateX(0);
        grid-template-rows: 1fr;
      }
    }
    
    @keyframes close-menu {
      from {
        transform: translateX(0);
        grid-template-rows: 1fr;
      }
      to {
        transform: translateX(0);
        grid-template-rows: 0fr;
      }
    }
    
    /* Necessary to collapse with grid-template-columns */
    #menu-bar {
      overflow: hidden;
    }
    
    .menu #menu-bar li {
      color: whitesmoke;
      display: inline-block;
      padding: 10px;
      align-items: center;
      font-size: 20px;
      transition: background-color 400ms ease;
    }
    
    .menu #menu-bar li:hover {
      background-color: rgb(175, 175, 175);
      border-radius: 5px;
      color: rgb(65, 65, 65);
    }
    
    #test {
      height: 1000px;
      background-color: rgb(0, 0, 0);
      color: white;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <link rel="stylesheet" href="style.css">
      <script src="code.js"></script>
    </head>
    
    <body>
      <div class="top">
        <div id="cool-lookin-box">
          <p>TESTOWY TEXT</p>
        </div>
        <div class="menu">
          <ul id="menu-bar">
            <li>First</li>
            <li>Second</li>
            <li>Third</li>
            <li>Fourth</li>
            <a href="https://google.com">
              <li>Fifth</li>
            </a>
          </ul>
        </div>
      </div>
      <div id="test"></div>
    </body>
    
    </html>

    I hope that helps!