向下滑动汉堡菜单

Slide down burger menu

我想知道是否有办法在我的菜单下拉菜单中循环 height 并使其向下滑动,而不是像现在这样显示?

我正在尝试做这样的事情:

var list = document.getElementById("list");
var listElements = list.childElementCount;
var height = 1.5 * listElements;
var x = document.getElementById("burgerMenu");
if (x.style.height === "0rem") {
    x.style.height = height + "rem";
} else {
    x.style.height = "0rem";
}

但是好像不太对...

我知道我需要添加一个 transition,然后更改 div 的高度,但我对具体方法有点困惑。

JS 事件侦听器只监听 three 行是否有点击,或者如果是其他情况,它会删除 class(三行之外)或切换(点击三行)。

我认为动画应该在 topnav-menu 上,或者我错了,因为这是包含内容的 div。

window.addEventListener('click', function(e) {
    var menu = document.querySelector('.right-nav');
    if (!document.querySelector('.outsideOfBurger').contains(e.target)) {
        // Outside of burger menu / item clicked inside the burger menu
        menu.classList.remove('open-hamburguer');
    } else {
        // Three burger menu lines clicked, so we toggle hide/show
        menu.classList.toggle('open-hamburguer');
    }
});
:root {
    /* Static Colors*/
    --clr-heading-footer: #4C5BA0;
    --clr-button: #4C5BA0;
    --clr-nav-color: #8D90A1;
    /* (Default) Page Settings */
    height: 100%;
    font-family: 'Montserrat';
    padding: 2% 12%;
    --clr-box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
}

body {
    background: var(--background);
    color: var(--foreground);
}

.logo-style {
    /* Logo Style */
    font-style: normal;
    font-weight: bold;
    font-size: 2rem;
    line-height: 2.438rem;
    letter-spacing: 0.05em;
    color: #4C5BA0;
    margin: 0;
}


/*
    Navigation
*/

.topnav {
    background: none !important;
    align-items: center;
    display: flex;
    justify-content: space-between;
}

.topnav a {
    color: blue;
    text-align: center;
    padding: 0.09rem 0.30rem;
    text-decoration: none;
    font-size: 1.063rem;
}

.right-nav {
    display: flex;
    flex-direction: row;
    gap: 0.625rem;
    align-items: center;
    position: relative;
}


.topnav-menu {
    /* Burger Menu Content*/
    width: 300px;
    transition: all .5s ease;
    background-color: none;
    padding: 0;
    max-height: 0;
    position: absolute;
    top: 100%;
    /* distance itself 100% of the height of parent element */
    right: 0;
    /* aligned on the right of container */
    opacity: 0;
    display: none;
    /* just to hide it (overwritten when toggle('open-hamburguer') is clicked) */
}

.open-hamburguer .topnav-menu {
    opacity: 1;
    display: block;
    max-height: 300px;
    /* here is the only thing you could add find out through js because you can't animate the height */
}

.topnav-menu ul {
    /* Burger Menu Content*/
    margin: 0;
    padding: 0;
    list-style: none;
    box-shadow: var(--clr-box-shadow);
    border-radius: 15px;
    /* border-radius is also set here else the shadow looks wired */
}

.topnav-menu ul li:last-child {
    border-top: 1px solid gray;
    /* last item border -> above Login/Logout */
}

.topnav-menu ul li:first-child a {
    border-radius: 15px 15px 0 0;
    /* round borders on start */
}

.topnav-menu ul li:last-child a {
    border-radius: 0 0 15px 15px;
    /* round borders on end */
}

.topnav-menu a {
    color: var(--clr-nav-color);
    background-color: var(--menu-card-color);
    display: block;
    text-align: left;
    padding: 0.313rem 0.313rem;
    text-decoration: none;
    font-size: 1.063rem;
    transition: all .5s ease;
}

.topnav-menu a:hover {
    color: black;
}

.topnav-menu a.active {
    color: black;
}


/*
    Navigation Burger Menu
*/

.line-one {
    width: 1.875rem;
}

.line-two {
    width: 1.875rem;
}

.line-three {
    width: 1.875rem;
}

.burger-menu div {
    width: 1.875rem;
    height: 0.25rem;
    background-color: var(--clr-nav-color);
    margin: 0.313rem 0;
    border-radius: 1.563rem;
}

.burger-menu {
    width: 1.875rem;
}

.burger-menu:hover div {
    width: 1.875rem;
    background-color: black;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Metrics</title>
    <link href="https://fonts.googleapis.com/css?family=Montserrat:600" rel="stylesheet">
</head>
<body>
    <header>
        <div class="topnav">
            <div class="left-nav">
                <a href="#home"><p class="logo-style">Metrics</p></a>
            </div>
            <div class="right-nav">
                <a href="#burger-menu" class="burger-menu outsideOfBurger">
                    <div class="line-one"></div>
                    <div class="line-two"></div>
                    <div class="line-three"></div>
                </a>

              <div class="topnav-menu outsideOfBurger" id="burgerMenu">
                  <div>
                      <ul id="list">
                          <li><a href="#item1">Overall sprint progress </a></li>
                          <li><a href="#item2">This is a bit longer text to show it splits into new line</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item4">Info</a></li>
                          <li><a href="#logout">Logout</a></li>
                      </ul>
                  </div>
              </div>
            </div>
        </div>
    </header>
</body>
</html>

你可以给height:0代替display:none来实现幻灯片切换。还要添加 overflow:hidden 这样当高度为 0 时它就不会显示内容,一旦菜单切换你就可以给 height:auto

window.addEventListener('click', function(e) {
    var menu = document.querySelector('.right-nav');
    if (!document.querySelector('.outsideOfBurger').contains(e.target)) {
        // Outside of burger menu / item clicked inside the burger menu
        menu.classList.remove('open-hamburguer');
    } else {
        // Three burger menu lines clicked, so we toggle hide/show
        menu.classList.toggle('open-hamburguer');
    }
});
:root {
    /* Static Colors*/
    --clr-heading-footer: #4C5BA0;
    --clr-button: #4C5BA0;
    --clr-nav-color: #8D90A1;
    /* (Default) Page Settings */
    height: 100%;
    font-family: 'Montserrat';
    padding: 2% 12%;
    --clr-box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
}

body {
    background: var(--background);
    color: var(--foreground);
}

.logo-style {
    /* Logo Style */
    font-style: normal;
    font-weight: bold;
    font-size: 2rem;
    line-height: 2.438rem;
    letter-spacing: 0.05em;
    color: #4C5BA0;
    margin: 0;
}


/*
    Navigation
*/

.topnav {
    background: none !important;
    align-items: center;
    display: flex;
    justify-content: space-between;
}

.topnav a {
    color: blue;
    text-align: center;
    padding: 0.09rem 0.30rem;
    text-decoration: none;
    font-size: 1.063rem;
}

.right-nav {
    display: flex;
    flex-direction: row;
    gap: 0.625rem;
    align-items: center;
    position: relative;
}


.topnav-menu {
    /* Burger Menu Content*/
    width: 300px;
    transition: all .5s ease;
    background-color: none;
    padding: 0;
    max-height: 0;
    position: absolute;
    top: 100%;
    /* distance itself 100% of the height of parent element */
    right: 0;
    /* aligned on the right of container */
    opacity: 0;
    height:0;
    overflow:hidden;
    /* just to hide it (overwritten when toggle('open-hamburguer') is clicked) */
}

.open-hamburguer .topnav-menu {
    opacity: 1;
    display: block;
    max-height: 300px;
height:auto;
    /* here is the only thing you could add find out through js because you can't animate the height */
}

.topnav-menu ul {
    /* Burger Menu Content*/
    margin: 0;
    padding: 0;
    list-style: none;
    box-shadow: var(--clr-box-shadow);
    border-radius: 15px;
    /* border-radius is also set here else the shadow looks wired */
}

.topnav-menu ul li:last-child {
    border-top: 1px solid gray;
    /* last item border -> above Login/Logout */
}

.topnav-menu ul li:first-child a {
    border-radius: 15px 15px 0 0;
    /* round borders on start */
}

.topnav-menu ul li:last-child a {
    border-radius: 0 0 15px 15px;
    /* round borders on end */
}

.topnav-menu a {
    color: var(--clr-nav-color);
    background-color: var(--menu-card-color);
    display: block;
    text-align: left;
    padding: 0.313rem 0.313rem;
    text-decoration: none;
    font-size: 1.063rem;
    transition: all .5s ease;
}

.topnav-menu a:hover {
    color: black;
}

.topnav-menu a.active {
    color: black;
}


/*
    Navigation Burger Menu
*/

.line-one {
    width: 1.875rem;
}

.line-two {
    width: 1.875rem;
}

.line-three {
    width: 1.875rem;
}

.burger-menu div {
    width: 1.875rem;
    height: 0.25rem;
    background-color: var(--clr-nav-color);
    margin: 0.313rem 0;
    border-radius: 1.563rem;
}

.burger-menu {
    width: 1.875rem;
}

.burger-menu:hover div {
    width: 1.875rem;
    background-color: black;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Metrics</title>
    <link href="https://fonts.googleapis.com/css?family=Montserrat:600" rel="stylesheet">
</head>
<body>
    <header>
        <div class="topnav">
            <div class="left-nav">
                <a href="#home"><p class="logo-style">Metrics</p></a>
            </div>
            <div class="right-nav">
                <a href="#burger-menu" class="burger-menu outsideOfBurger">
                    <div class="line-one"></div>
                    <div class="line-two"></div>
                    <div class="line-three"></div>
                </a>

              <div class="topnav-menu outsideOfBurger" id="burgerMenu">
                  <div>
                      <ul id="list">
                          <li><a href="#item1">Overall sprint progress </a></li>
                          <li><a href="#item2">This is a bit longer text to show it splits into new line</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item3">Somthing</a></li>
                          <li><a href="#item4">Info</a></li>
                          <li><a href="#logout">Logout</a></li>
                      </ul>
                  </div>
              </div>
            </div>
        </div>
    </header>
</body>
</html>