Make a card burger menu dropdown

Okay so this is a bit of a longer code I’ve posted but I will try to explain what I’m trying to do here.

I have this burger menu icon to the right (three lines), and when these are clicked I want by items to slide down and be viewed like in this image

enter image description here

In my example you can see how I created the first part of it, but I don’t know how to make this part, since position: absolute; and so on makes it look wired, and it starts to float in the right corner. I know I still need to round the corners and make some shadows, but that not the hard part. I’ve seen people using <nav> tags with <divs> inside instead of the way I do it with div outside and <ul> lists inside, but is that better or can this still be done, and how?

Example

function menuToggle() {
    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";
    }
}
:root {
    /* Static Colors*/
    --clr-heading-footer: #4C5BA0;
    --clr-button: #4C5BA0;
    --clr-nav-color: #8D90A1;
    /* Dark Theme */
    --clr-bg-dark: #2F2F35;
    --clr-card-bg-dark: #3A3B41;
    --clr-card-body-text-dark: #8D90A1;
    --clr-card-title-text-dark: #D3D3D9;
    --clr-nav-activ-color-dark: #D3D3D9;
    --clr-nav-hover-color-dark: #D3D3D9;
    --dark-moon: url("../images/svg/dark_moon.svg") center no-repeat;
    --dark-hover-moon: url("../images/svg/dark_moon_hover.svg") center no-repeat;
    /* (Default) Light Theme */
    --clr-bg-light: #E1E1E1;
    --clr-card-bg-light: #F3F3F3;
    --clr-nav-activ-color-light: #3A3B41;
    --clr-nav-hover-color-light: #3A3B41;
    --light-sun: url("../images/svg/light_sun.svg") center no-repeat;
    --light-hover-sun: url("../images/svg/light_sun_hover.svg") center no-repeat;
    /* (Default) Set Colors */
    --foreground: var(--clr-bg-dark);
    --background: var(--clr-bg-light);
    --activ-mode-icon: var(--light-sun);
    --activ-hover-mode-icon: var(--light-hover-sun);
    --selected-nav-page: var(--clr-nav-activ-color-light);
    --hover-nav: var(--clr-nav-hover-color-light);
    /* (Default) Page Settings */
    height: 100%;
    font-family: 'Montserrat';
    padding: 2% 12%;
    --speed: .3s;
}

.darkmodescss {
    /* Used as classList.add('darkmodescss') by js/toggletheme.js
    Replaces the (Default) Light Theme parameters with Dark Theme */
    --foreground: var(--clr-bg-light);
    --background: var(--clr-bg-dark);
    --activ-mode-icon: var(--dark-moon);
    --activ-hover-mode-icon: var(--dark-hover-moon);
    --selected-nav-page: var(--clr-nav-activ-color-dark);
    --hover-nav: var(--clr-nav-hover-color-dark);
    --clr-icon-width: var(--clr-icon-width);
    --clr-icon-height: var(--clr-icon-height);
}

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 {
    overflow: hidden;
    background: none !important;
    align-items: center;
    display: flex;
    justify-content: space-between;
}

.topnav button {
    border: none;
    cursor: pointer;
}

.topnav a {
    color: var(--clr-nav-color);
    text-align: center;
    padding: 0.09rem 0.30rem;
    text-decoration: none;
    font-size: 1.063rem;
}

.topnav a:hover {
    color: var(--hover-nav);
}

.topnav a.active {
    color: var(--selected-nav-page);
}

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

.nav-icon {
    /* Navigation Icon Sizing - SVG Only */
    width: 2em;
    height: 2em;
    padding: 0.09rem 0.15rem;
    margin-left: 0.5rem;
    margin-right: 0.5rem;
}

.disp_mode {
    /* (Default) Dark / Light Mode - Icon Handling */
    background: var(--activ-mode-icon) no-repeat;
}

.disp_mode:hover {
    /* (Hover) Dark / Light Mode - Icon Handling */
    background: var(--activ-hover-mode-icon) no-repeat;
}

.topnav-menu {
    /* Burger Menu Content*/
    width: 100%;
    overflow: hidden;
    transition: 1000ms;
    background-color: none;
    padding: 0;
}

.topnav-menu ul {
    /* Burger Menu Content*/
    float: right;
    margin: 0;
    list-style-type: none;
}

.topnav-menu a {
    color: var(--clr-nav-color);
    text-align: center;
    padding: 0.313rem 0.313rem;
    text-decoration: none;
    font-size: 1.063rem;
}

.topnav-menu a:hover {
    color: var(--hover-nav);
}

.topnav-menu a.active {
    color: var(--selected-nav-page);
}


/*
    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: var(--hover-nav);
}
<?php
    declare(strict_types=1);
?>
<!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="#home" class="active">Home</a>
                <a href="#archives">Archives</a>
                <a href="#coverage">Coverage</a>
                <a href="#burger-menu" class="burger-menu" onclick="menuToggle()">
                    <div class="line-one"></div>
                    <div class="line-two"></div>
                    <div class="line-three"></div>
                </a>
            </div>
        </div>
        <!-- Burger Menu Hidden By Default Untill menuToggle() is activated -->
        <div class="topnav-menu" id="burgerMenu" style="height:0rem;">
            <div>
                <ul id="list">
                    <li><a href="#item1">Overall sprint progress </a></li>
                    <li><a href="#item2">item2</a></li>
                    <li><a href="#login">Logout</a></li>
                </ul>
            </div>
        </div>
    </header>
</body>
</html>

I found another example where they made it in css, and it could probably also be done like that even though I can’t make it work?

Link to a CSS only dropdown

Answer

TL:DR that’s a lot of code for something so simple. Don’t rely on javascript to do the animations, just to put a “open” class on the css element. About the positioning, you need to tell the element which parent to use it’s positioning, in this case, the hamburguer.

Also, you want the menu inside the DOM component it is parent of, in this case, the hamburguer menu it would be better inside the place where it should appear.

Let me try to solve it:

function menuToggle() {
  var menu = document.querySelector('.right-nav');
  menu.classList.toggle('open-hamburguer');
}
:root {
    /* Static Colors*/
    --clr-heading-footer: #4C5BA0;
    --clr-button: #4C5BA0;
    --clr-nav-color: #8D90A1;
    /* Dark Theme */
    --clr-bg-dark: #2F2F35;
    --clr-card-bg-dark: #3A3B41;
    --clr-card-body-text-dark: #8D90A1;
    --clr-card-title-text-dark: #D3D3D9;
    --clr-nav-activ-color-dark: #D3D3D9;
    --clr-nav-hover-color-dark: #D3D3D9;
    --dark-moon: url("../images/svg/dark_moon.svg") center no-repeat;
    --dark-hover-moon: url("../images/svg/dark_moon_hover.svg") center no-repeat;
    /* (Default) Light Theme */
    --clr-bg-light: #E1E1E1;
    --clr-card-bg-light: #F3F3F3;
    --clr-nav-activ-color-light: #3A3B41;
    --clr-nav-hover-color-light: #3A3B41;
    --light-sun: url("../images/svg/light_sun.svg") center no-repeat;
    --light-hover-sun: url("../images/svg/light_sun_hover.svg") center no-repeat;
    /* (Default) Set Colors */
    --foreground: var(--clr-bg-dark);
    --background: var(--clr-bg-light);
    --activ-mode-icon: var(--light-sun);
    --activ-hover-mode-icon: var(--light-hover-sun);
    --selected-nav-page: var(--clr-nav-activ-color-light);
    --hover-nav: var(--clr-nav-hover-color-light);
    /* (Default) Page Settings */
    height: 100%;
    font-family: 'Montserrat';
    padding: 2% 12%;
    --speed: .3s;
}

.darkmodescss {
    /* Used as classList.add('darkmodescss') by js/toggletheme.js
    Replaces the (Default) Light Theme parameters with Dark Theme */
    --foreground: var(--clr-bg-light);
    --background: var(--clr-bg-dark);
    --activ-mode-icon: var(--dark-moon);
    --activ-hover-mode-icon: var(--dark-hover-moon);
    --selected-nav-page: var(--clr-nav-activ-color-dark);
    --hover-nav: var(--clr-nav-hover-color-dark);
    --clr-icon-width: var(--clr-icon-width);
    --clr-icon-height: var(--clr-icon-height);
}

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 {
    /*overflow: hidden; *//* if this is set the hamburguer don't show inside. it is best to the hamburguer to be inside to know the positioning of the other elements he wants to be near */
    background: none !important;
    align-items: center;
    display: flex;
    justify-content: space-between;
}

.topnav button {
    border: none;
    cursor: pointer;
}

.topnav a {
    color: var(--clr-nav-color);
    text-align: center;
    padding: 0.09rem 0.30rem;
    text-decoration: none;
    font-size: 1.063rem;
}

.topnav a:hover {
    color: var(--hover-nav);
}

.topnav a.active {
    color: var(--selected-nav-page);
}

.right-nav {
    display: flex;
    flex-direction: row;
    gap: 0.625rem;
    align-items: center;
    position:relative; /* all other positioned elements should use this as the indicator */
}

.nav-icon {
    /* Navigation Icon Sizing - SVG Only */
    width: 2em;
    height: 2em;
    padding: 0.09rem 0.15rem;
    margin-left: 0.5rem;
    margin-right: 0.5rem;
}

.disp_mode {
    /* (Default) Dark / Light Mode - Icon Handling */
    background: var(--activ-mode-icon) no-repeat;
}

.disp_mode:hover {
    /* (Hover) Dark / Light Mode - Icon Handling */
    background: var(--activ-hover-mode-icon) no-repeat;
}

.topnav-menu {
    /* Burger Menu Content*/
    width: 300px; /* can't assume the parents width */
    overflow: hidden; /* this hides the shadow from inside, but we add some padding to fix this v */
    padding: 5px;
    transition: all .5s ease; /* !! */
    background-color: none;
    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; /* just to hide it */
}
/* here the magic happens */
.open-hamburguer .topnav-menu{
   opacity:1;
   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*/
    /* float: right;*/ /* no need */
    margin: 0;
    padding:0; /* yes need */
    list-style: none; /* shorthand */
    box-shadow: 0 2px 2px gray; /* shorthand */
    border-radius:10px; /* have to set here too otherwise the shadow would be weird */
}

.topnav-menu ul li:last-child {
    border-top:1px solid gray; /* last item border */
}
.topnav-menu ul li:last-child a {
    border-radius:0 0 10px 10px; /* round borders on end */
}
.topnav-menu ul li:first-child a {
    border-radius:10px 10px 0 0; /* round borders on start */
}

.topnav-menu a {
    background-color:white; /* best to have background for each link instead of container */
    display:block; /* inline elements are a bother */
    text-align:left; /* !! */
    color: var(--clr-nav-color);
    text-align: left;
    padding: 0.313rem 0.313rem;
    padding: 0.8rem 1rem; /* rem is not a good measure for this, if for some reason you want to increase the base font for text this all goes south */
    text-decoration: none;
    font-size: 1.063rem;
    transition:all .5s ease; /* pretty */
}

.topnav-menu a:hover {
    color: var(--hover-nav);
    background-color:orange; /* cmon some color :P */
}

.topnav-menu a.active {
    color: var(--selected-nav-page);
}


/*
    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: var(--hover-nav);
}
<?php
    declare(strict_types=1);
?>
<!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="#home" class="active">Home</a>
                <a href="#archives">Archives</a>
                <a href="#coverage">Coverage</a>
                <a href="#burger-menu" class="burger-menu" onclick="menuToggle()">
                    <div class="line-one"></div>
                    <div class="line-two"></div>
                    <div class="line-three"></div>
                </a>

              <!-- Burger Menu Hidden By Default Untill menuToggle() is activated -->
              <div class="topnav-menu" id="burgerMenu">
                  <div>
                      <ul id="list">
                          <li><a href="#item1">Overall sprint progress </a></li>
                          <li><a href="#item2">item2</a></li>
                          <li><a href="#login">Logout</a></li>
                      </ul>
                  </div>
              </div>
            </div>
        </div>
    </header>
</body>
</html>

You get the point. Next time please try to share the code only for the subject at hand, it was hard running through this code that wasn’t related.

Fun tho’

Edit

Actually added the overflow:hidden from the menu so you can’t see the contents when the height is 0, to avoid hiding the box-shadow I added a little padding.