[JavaScript/CSS] Dropdown Menu 動畫效果 (由右往左的甩尾)

Dropdown Menu Animations (Right To Left)

前言

最近正製作手機用的RWD網頁,CSS框架採用Bootstrap,官網Navbar看來看去一直覺得垂直式的選單動畫效果

如果要改起來方便快速的話,似乎就這麼兩種:下滑SlideDown(預設)、淡入

https://bootstrap.hexschool.com/docs/4.0/components/navbar/

突然心血來潮想自己實現究竟選單能不能由左往右或由右往左滑入呢XD

很幸運地上Youtube找到一位外國人的各種選單炫技影片:Drop Down Menu — CSS Animations

其中第四個選單有接近我的需求,雖然他寫的是Sass語法讓我看得略懂略懂

但經過一晚的努力,我還是寫出自己想要的選單動畫效果,放上部落格備份一下(畢竟辛苦試超久,跟Youtube影片比起來,我減少很多程式碼XD)

※2019-01-01追記:Youtube上找到和本文類似效果的教學文 Let's Codepen: #1 CSS Animated Dropdown Menu

實作

※本文使用Bootstrap 4版本


<!doctype html>
<html>
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
       <style type="text/css">
           

     /*定義動畫執行多久完成,一般都是300ms~800ms就差不多*/
    ul.navbar-nav > li {
    animation-duration: 0.4s;
    }
 




/*定義CSS動畫效果(淡入、由右往左移)*/
@keyframes animation-li1 {
    0% {
        opacity: 0;
        transform: translateX(30px);
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}

@keyframes animation-li2 {
    0% {
        opacity: 0;
        transform: translateX(40px); /*+10*/
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}

@keyframes animation-li3 {
    0% {
        opacity: 0;
        transform: translateX(60px);/*加20*/
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}

@keyframes animation-li4 {
    0% {
        opacity: 0;
        transform: translateX(90px);/*加30*/
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}

@keyframes animation-li5 {
    0% {
        opacity: 0;
        transform: translateX(130px);/*加40*/
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}

@keyframes animation-li6 {
    0% {
        opacity: 0;
        transform: translateX(180px); /*加50*/
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}
@keyframes animation-li7 {
    0% {
        opacity: 0;
        transform: translateX(240px); /*加60*/
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}
@keyframes animation-li8 {
    0% {
        opacity: 0;
        transform: translateX(310px); /*加70*/
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}
@keyframes animation-li9 {
    0% {
        opacity: 0;
        transform: translateX(390px); /*加80*/
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}
@keyframes animation-li10 {
    0% {
        opacity: 0;
        transform: translateX(480px); /*加90,加的數字隨自己喜好調整,我喜歡愈底下的li愈有甩尾效果,所以才調出以上數字*/
    }

    100% {
        opacity: 1;
        transform: translateX(0px);
    }
}

/*↓註解掉的看個人喜好,如果小營幕才套用動畫效果*/
/*@media (max-width:767px) {*/
           
/*為每個li項目套用動畫*/
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(1)
{
    animation-name: animation-li1;
}
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(2) {
    animation-name: animation-li2;
}
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(3) {
    animation-name: animation-li3;
}
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(4) {
    animation-name: animation-li4;
}
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(5) {
    animation-name: animation-li5;
}
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(6) {
    animation-name: animation-li6;
}
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(7) {
    animation-name: animation-li7;
}
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(8) {
    animation-name: animation-li8;
}
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(9) {
    animation-name: animation-li9;
}
div#navbarSupportedContent > ul.navbar-nav  > li:nth-child(10) {
    animation-name: animation-li10;
}

           /*}*/


div#navbarSupportedContent
{
   overflow-x: hidden; /*避免動畫執行期間出現捲軸*/ 
}
       </style>
  </head>
  <body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Navbar</a>

        <%--把data-toggle="collapse" data-target="#navbarSupportedContent" 這兩個拿掉,改用jQuery trigger選單--%>
  <button class="navbar-toggler" type="button" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>

  <div class="collapse navbar-collapse" id="navbarSupportedContent">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Link1</a>
      </li>
      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          Dropdown
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
          <a class="dropdown-item" href="#">Action</a>
          <a class="dropdown-item" href="#">Another action</a>
          <div class="dropdown-divider"></div>
          <a class="dropdown-item" href="#">Something else here</a>
        </div>
      </li>
        <li class="nav-item">
        <a class="nav-link" href="#">Link2</a>
      </li>
        <li class="nav-item">
        <a class="nav-link" href="#">Link3</a>
      </li>
        <li class="nav-item">
        <a class="nav-link" href="#">Link4</a>
      </li>
        <li class="nav-item">
        <a class="nav-link" href="#">Link5</a>
      </li>
        <li class="nav-item">
        <a class="nav-link" href="#">Link8</a>
      </li>
        <li class="nav-item">
        <a class="nav-link" href="#">Link9</a>
      </li>
       <li class="nav-item">
        <a class="nav-link" href="#">Link10</a>
      </li>
    </ul>
 
  </div>
</nav>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
      <script type="text/javascript">
        //只有小營幕時,按鈕才會出現
          $("button.navbar-toggler").click(function () {
              $div = $("#navbarSupportedContent");
              if ($div.hasClass("show"))
              {//隱藏選單
                  $div.removeClass("show");
              } else {
                  //否則顯示選單
                  $div.addClass("show");
              }
          });
      </script>
  </body>
</html>

線上執行結果請看:JSFiddle

另外該Youtube影片有提供練習程式碼,不過它沒有響應式:Drop Down Menu — CSS Animations

我也把自己練習完成的程式碼順便公開

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <style type="text/css">
        nav {
            padding: 50px;
            text-align: center;
        }

            nav > ul {
                list-style: none;
                padding: 0;
                margin: 0;
                display: inline-block;
                background: #ddd;
                border-radius: 5px;
            }

                nav > ul > li {
                    float: left;
                    width: 150px;
                    height: 65px;
                    line-height: 65px;
                    position: relative;
                    text-transform: uppercase;
                    font-size: 14px;
                    color: rgba(0, 0, 0, 0.7);
                    cursor: pointer;
                }

                    nav > ul > li:hover {
                        background: #d5d5d5;
                        border-radius: 5px;
                    }

        ul.drop-menu {
            position: absolute;
            top: 100%;
            left: 0%;
            width: 100%;
            padding: 0;
        }

            ul.drop-menu li {
                background: #666;
                color: rgba(255, 255, 255, 0.7);
            }

                ul.drop-menu li:hover {
                    background: #606060;
                }

                ul.drop-menu li:last-child {
                    border-radius: 0px 0px 5px 5px;
                }

               
                



                
            /*預設第二層選單li隱藏*/
            ul.drop-menu li {
                display: none;
            }
            /*當第一層選單項目hover時,第二層選單li顯示*/ 
             li:hover > ul.drop-menu li { 
              display: block; 
             }  
            /*以上兩個樣式使用以下兩個樣式取代也可以*/

            /*
            ul.drop-menu {
             display: none;
            } 
            li:hover > ul.drop-menu { 
               display: block;  
             }*/
            

        /*All MENU  ---------------*/
        /*第二層選單,每個li項目動畫執行期間為400ms*/
        ul.drop-menu > li {
            animation-duration: 0.4s;
        }

        /*為第二層每個li套用動畫*/
        ul.drop-menu > li:nth-child(1) {
            animation-name: animation-li1;
        }

        ul.drop-menu > li:nth-child(2) {
            animation-name: animation-li2;
        }

        ul.drop-menu > li:nth-child(3) {
            animation-name: animation-li3;
        }

        ul.drop-menu > li:nth-child(4) {
            animation-name: animation-li4;
        }

        ul.drop-menu > li:nth-child(5) {
            animation-name: animation-li5;
        }

        ul.drop-menu > li:nth-child(6) {
            animation-name: animation-li6;
        }


        /*定義CSS動畫效果*/
        @keyframes animation-li1 {
            0% {
                opacity: 0;
                transform: translateX(30px);
            }

            100% {
                opacity: 1;
                transform: translateX(0px);
            }
        }

        @keyframes animation-li2 {
            0% {
                opacity: 0;
                transform: translateX(40px); /*+10*/
            }

            100% {
                opacity: 1;
                transform: translateX(0px);
            }
        }

        @keyframes animation-li3 {
            0% {
                opacity: 0;
                transform: translateX(60px); /*加20*/
            }

            100% {
                opacity: 1;
                transform: translateX(0px);
            }
        }

        @keyframes animation-li4 {
            0% {
                opacity: 0;
                transform: translateX(90px); /*加30*/
            }

            100% {
                opacity: 1;
                transform: translateX(0px);
            }
        }

        @keyframes animation-li5 {
            0% {
                opacity: 0;
                transform: translateX(130px); /*加40*/
            }

            100% {
                opacity: 1;
                transform: translateX(0px);
            }
        }

        @keyframes animation-li6 {
            0% {
                opacity: 0;
                transform: translateX(180px); /*加50*/
            }

            100% {
                opacity: 1;
                transform: translateX(0px);
            }
        }
    </style>
</head>
<body>






    <nav>
        <ul>
            <li>style 1
      <ul class="drop-menu menu-1">
          <li>uno</li>
          <li>dos</li>
          <li>tres</li>
          <li>cuatro</li>
          <li>cinco</li>
          <li>seis</li>
      </ul>
            </li>
            <li>style 2
      <ul class="drop-menu menu-2">
          <li>uno</li>
          <li>dos</li>
          <li>tres</li>
          <li>cuatro</li>
          <li>cinco</li>
          <li>seis</li>
      </ul>
            </li>
            <li>style 3
      <ul class="drop-menu menu-3">
          <li>uno</li>
          <li>dos</li>
          <li>tres</li>
          <li>cuatro</li>
          <li>cinco</li>
          <li>seis</li>
      </ul>
            </li>
            <li>style 4
      <ul class="drop-menu menu-4">
          <li>uno</li>
          <li>dos</li>
          <li>tres</li>
          <li>cuatro</li>
          <li>cinco</li>
          <li>seis</li>
      </ul>
            </li>
        </ul>
    </nav>


</body>
</html>

↑線上執行結果請看:JSFiddle