Creating a dynamic navigation menu with ul and li elements that adapts to

Lately, I've been experimenting with transforming a horizontal menubar into a drop-down hamburger menu for smaller screens by following various tutorials. However, I'm encountering difficulties in getting everything to work seamlessly. Many of the tutorials I've come across abandon the ul/li format, which I prefer to keep for semantic and accessibility reasons. This decision has made it challenging for me to ensure the dropdown menu appears correctly on the screen.

My objective is to have the hamburger menu open four menu items, centered on the screen below the top header bar. I've made progress in making the hamburger menu functional, but it's currently opening the items off-center and not below the top menubar. Are there any suggestions that could help me achieve this without having to completely overhaul the menubar code?

Snippet:

const menu = document.querySelector(".nav");
let open;

function openMenu() {
  if (open) {
    menu.style.display = "none";
    open = false;
  } else if (!open) {
    menu.style.display = "block";
    open = true;
  }
}
.menubar {
  width: 100%;
  height: 50px;
  line-height: 50px;
  vertical-align: middle;
  background-color: #fff;
  border-bottom: 1px solid #f5f5f5;
  position: fixed;
  top: 0;
  -webkit-user-select: all;
  user-select: none;
  display: flex;
  align-items: center;
}

.logo {
  font-size: 24px;
  display: flex;
  align-items: center;
  padding-left: 15px;
  position: absolute;
}

.nav {
  display: flex;
  font-size: 18px;
  flex-direction: row;
  list-style: none;
  margin: 0 auto;
  padding: 0;
}

.nav li {
  margin: 0 15px;
}

.hamburger {
  margin: 0 13px 0 auto;
  height: inherit;
}

@media screen and (min-width: 801px) {
  .nav {
    display: flex !important;
  }
  .hamburger {
    display: none;
  }
}

@media screen and (max-width: 800px) {
  .hamburger {
    display: flex;
  }
  .nav {
    display: none;
    text-align: center;
  }
}
<body>
  <div class="menubar">
    <a href="" class="logo">WEBSITE NAME</a>
    <ul class="nav">
      <li><a href="">HOME</a></li>
      <li><a href="">MENU1</a></li>
      <li><a href="">MENU2</a></li>
      <li><a href="">ABOUT</a></li>
    </ul>

    <input type="image" class="hamburger" onclick={openMenu()} src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/800px-Hamburger_icon.svg.png" />
  </div>
</body>

Check out the accompanying JSFiddle.

Answer №1

One way to handle window resizing is by adding a listener that triggers when the window size changes. If the window width goes below 800px, a specific class can be added to an element.

In this case, the script adds a class called .mobile and updates the styling for the mobile menu accordingly.

To implement this functionality in your JS code:

    window.addEventListener('resize', setMobileClass);
    window.addEventListener('load', setMobileClass);

    function setMobileClass() {
        if (window.innerWidth <= 800) {
            menu.classList.add('mobile');
        } else {
            menu.classList.remove('mobile');
        }
    };

Add these CSS rules as well:

    .mobile {
        position: absolute;
        right: 0px;
        top: 50px;
    }

Here's an example setup:

const menu = document.querySelector(".nav");
let open;

function openMenu() {
    if (open) {
        menu.style.display = "none";
        open = false;
    } else if (!open) {
        menu.style.display = "block";
        open = true;
    }
}

window.addEventListener('resize', setMobileClass);
window.addEventListener('load', setMobileClass);

function setMobileClass() {
    if (window.innerWidth <= 800) {
        menu.classList.add('mobile');
    } else {
        menu.classList.remove('mobile');
    }
};
.menubar {
    /* CSS styles for menubar */
}

/* Other CSS styles for navigation, logo, and hamburger icon */

.mobile {
    position: absolute;
    right: 0px;
    top: 50px;
}
<div class="menubar">
    <a href="" class="logo">WEBSITE NAME</a>
    <ul class="nav">
        <li><a href="">HOME</a></li>
        <li><a href="">MENU1</a></li>
        <li><a href="">MENU2</a></li>
        <li><a href="">ABOUT</a></li>
    </ul>

    <input type="image" class="hamburger" onclick={openMenu()}
        src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/800px-Hamburger_icon.svg.png" />
</div>

Answer №2

I came up with a stylish and effective solution inspired by 54ka's suggestion. Rather than implementing extra JavaScript code to add a mobile class, I decided to tweak the screen-size restricted nav class like this:

@media screen and (max-width: 800px) {
  .hamburger {
    display: flex;
  }
  .nav {
    display: none;
    position: absolute;
    text-align: center;
    width: 100%;
    right: 0px;
    top: 50px;
  }
}

By doing so, I ensured that the menu would be centered and positioned beneath the menubar. To enhance the dropdown menu further, you can include additional commands for background-color and borders.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Database query results displayed in a vertical scroll block

I'm facing an issue with the placement of a DIV tag on my page. I have a large number of rows being returned from a database query, and I can't seem to get the DIV tag in the right location. When I put the DIV tag outside the while loop, it appea ...

Implementing TinyMCE Styles into Your Published Content

Currently, I am integrating the TinyMCE editor into my React application. The CSS appears to be functioning properly within the editor itself, however, it does not carry over to the published content. Here is how I am rendering an element: <div ...

Dynamically change the fill color of an SVG using styled-components

I've been attempting to target the fill property of my SVG using CSS in styled-components without any luck. Here is my SVG: <svg width="65" height="19" viewBox="0 0 65 19" fill="none" xmlns="http://www. ...

What is the best way to create a line of divs within a row?

I am attempting to create a series of divs, with each div containing two rows. Here is the code I have so far: index.html <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8> <title>Rows and Divs</title&g ...

Connection to MondoDB via MongoClient in a Node.js environment has encountered an error and cannot

I've been attempting to establish a connection with my local MongoDB using the MongoDB NPM Package. Below is the code that I have been using: var express = require("express"); var router = express.Router(); var MongoClient = require('mongodb&apos ...

I want to display a div above an image when hovering over it

.vpbutton {padding:4px;background-color:#EFEFEF;} .userbox img{padding:8px;background-color:#EFEFEF;} .userbox img:hover{opacity:.2;} <div class="userbox"> <img src='img.png' style='height:120px;width:120px;border:1p ...

What steps do I need to take to ensure that this Regex pattern only recognizes percentages?

I am attempting to create a specific scenario where I can restrict my string to three digits, followed by a dot and two optional digits after the dot. For example: 100.00 1 10.56 31.5 I've developed a regex pattern that allows me to filter out any ...

Guide to executing a server request upon clicking a tab in asp.net using bootstrap

I managed to incorporate a tab system in my ASP.Net project using Bootstrap. <div> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"> <a href="#divrecentQ" id="linkdivrecentQ" aria ...

Database Records Showing '0' Value for Nullable Form Data

I am facing an issue with storing an empty input field in my database. I want it to be saved as "NULL", but when I submit the form with the input field empty, it gets stored as "0" in the database. In the controller, my code looks like this: $campaignRule ...

Having trouble retrieving input field values with Angular.js

I am struggling to access the input field values in my Angular.js application. Below is the code snippet I am using: <div class="input-group bmargindiv1 col-md-12"> <span class="input-group-addon ndrftextwidth text-right" style="width:180px"& ...

Exploring AngularJS: Filtering a nested JSON array

Just starting out with AngularJS and I could use some assistance. I have a JSON file that I've been working on, and I'm attempting to create a search filter by ingredient using AngularJS. Can anyone provide guidance? { "id": 01, "recipe- ...

Neglecting the Outcome of Async/Await

I am facing an issue where I need to send different SMS messages to different recipients synchronously, but my current implementation using async/await is not producing the expected results. Below is the code snippet causing the problem: Upon querying fo ...

Stopping a jQuery function from executing multiple times while it is already active - is it possible?

Currently, I am utilizing the http://jsfiddle.net/CqAU2/ plugin for image rotation on my website. The issue I am facing is that when the user clicks on the image box multiple times, it continues rotating each time. I want the click action to only be regi ...

My textbox occasionally appears devoid of any style

I am facing a puzzling issue with my Textboxes setup, defined as below: <table style="width: 100%; position: relative; top: -10px;"> <tr> <td style="font-size: 9pt; text-align: left;"> ...

BB10 - Capable of directing attention to text box, yet unable to input text

I developed a BB10 app that detects empty value fields and notifies users about them, prompting action by clicking 'OK' to focus on the text box. However, even though I can successfully place focus in the text box, I encounter an issue where I am ...

Ways to retrieve the content from an element embedded within a hyperlink using Python

Looking for a simple script that can be used to input a URL and extract the text of a specific HTML element on the page. For instance, if I input the URL , I would like to retrieve the "Position" value, which is CB in this example, and display it on my pag ...

Exploring the ancestry of Mongo

I am currently working on constructing a family tree that can have an infinite number of levels for parents and children. I am also interested in finding relationships like brothers, sisters, cousins, and so on. However, I'm facing some confusion when ...

Stop Bootstrap from impacting a specific division on my webpage

Is there a way to stop Bootstrap from impacting a specific div and its nested divs in my HTML document? Since adding Bootstrap, the images inside this particular div have turned dull and acquired an undesirable blue tint. Thank you for considering my conce ...

Selecting Specific File in Directory Using HTML File Input

Can you customize an HTML file input to choose a particular file from a directory or drive? By clicking on the file input button, the user opens the file selector and selects a folder or external drive. With jQuery, it is then possible to specify a specif ...

Tips for changing information in a child document using mongoose

My task involves updating the value of tQuan to 15 where the tName is FBK in the stocks array. I have been searching for a solution without success so far. It's important to note that I must adhere to the existing schema design without making any chan ...