Broad Network


How to Create a Hover-able Dropdown Menu inside a Responsive Horizontal Navigation Bar with CSS and JavaScript

Dropdown Menu

How To, for Web Applications

By: Chrysanthus Date Published: 16 Apr 2025

When the mouse pointer goes over a button, and a menu appears below the button, covering content that is below the button, that is a dropdown menu. This tutorial explains How to Create a Hover-able Dropdown Menu inside a Responsive Horizontal Navigation Bar with CSS and JavaScript. The drop-down menu consists of hyperlinks placed vertically. When the mouse pointer goes outside of the button or outside of the dropdown menu, the menu disappears. The button is in the horizontal navigation bar. Besides the button in the horizontal navigation bar, there are other menu items, which are hyperlinks. The use of the word, navigation, in this topic, means that the bar consists essentially of hyperlinks.

Now, for the project of this tutorial, with a wide device screen, there are five menu items in the horizontal navigation bar, in the order: Home, News, Contact, Dropdown, About; all flushed to the left. The Dropdown item is the button, which on-hover produces a dropdown menu. The rest of the items are hyperlinks.

The webpage is responsive in the sense that, when the device screen width is less than or equal to 600px, all the menu items disappear except the Home hyperlink. And then, the menu icon appears on the right of the shortened horizontal navigation bar. When the menu icon is clicked, the rest of the menu items that were there for the wide screen, appears under the Home hyperlink in a vertical form. At this state, when the mouse is over the dropdown button, the dropdown menu still appears. However, this time it pushes down other menu items below it. There is only one menu item below it, which is the About hyperlink.

At the end of this tutorial, is the complete webpage code. The reader should copy the complete code into a text editor. Save the file with any name, but with the extension, .html . Open the saved file in the browser. Hover over the button to see the dropdown menu. Next, reduce the width of the webpage continuously, until the menu icon appears. Click the menu icon, to see the horizontal menu bar develop into a vertical menu bar. Hover over the button again to see the same behavior of the dropdown menu. The reader is advised to do that before continuing to read the rest of this tutorial.

The Webpage Code Skeleton

The skeleton code for the webpage, to which more useful code will be added is:

    <!DOCTYPE html>
    <html>
    <head>
        <title>Responsive Topnav with Dropdown</title>
        <link rel='icon' href='https://www.examplee.com/images/logo.jpg' type='image/x-icon'>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="Description of the Web Page.">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

        <style>
        </style>

        <script type="text/javascript">
        </script>

    </head>
    <body>

    </body>
    </html>

Any modern professional webpage should have at least the first four tags in the HTML head element above. The fifth tag imports the solid lowercase v icon, that will be by the dropdown button. It imports it from the cloudflare.com website. The style element will have quite a good amount of code, which will make the menu appear and disappear, and also serve other purpose. The JavaScript will have short code which will become involved in responsive behavior. The menu container is a div element. The button element will be typed above the div element. Both the button and menu div are inside another div element, which is inside the horizontal bar div. All that content will be inside the HTML body element; not shown in the skeleton code above.

The Content of the HTML body Element

The content of the body element is:

        <div class="topnav" id="myTopnav">
            <a href="#home" class="active">Home</a>
            <a href="#news">News</a>
            <a href="#contact">Contact</a>
            <div class="dropdown">
                <button class="dropbtn">Dropdown <i class="fa fa-caret-down"></i></button>
                <div class="dropdown-content">
                    <a href="#">Link 1</a>
                    <a href="#">Link 2</a>
                    <a href="#">Link 3</a>
                </div>
            </div> 
            <a href="#about">About</a>
            <a href="javascript:void(0);" style="font-size:15px;" class="icon" onclick="myFunction()">☰</a>
        </div>

        <div style="padding-left:16px">
            <h2>Responsive Topnav with Dropdown</h2>
            <p>Resize the browser window to see how it works.</p>
            <p>Hover over the dropdown button to open the dropdown menu.</p>
        </div>

There are three div elements for the horizontal bar. There is the outermost div, with class-name "topnav" and ID "myTopnav". This is the div for the horizontal navigation bar. The first three elements in this div are hyperlinks (anchor elements), which are Home, News, and Contact. The next element in this div is an inner div, with class-name, "dropdown". The first element in this inner div, is the button element with class-name, "dropbtn". The next element in the inner div is an innermost div. This innermost div is the menu div for drop-down. Its class-name is "dropdown-content". It has three anchor (a) elements (hyperlinks). When it is dropped-down, its three hyperlinks are seen by the user.

The inner div with class-name, "dropdown" has two more elements after the innermost menu div. These two elements are hyperlinks. They are the About and the menu icon hyperlinks. With a small device screen, a vertical bar would result. In that state, when the drop-down occurs, the About hyperlink is pushed further downwards.

For wide device screens, the icon menu is not displayed. It is only displayed for small device screens on the right of the shortened horizontal bar, when only the Home menu item remains on the left of the shortened horizontal bar. When the menu icon is clicked, the rest of the hidden menu items that were in the horizontal bar for wide screens, form a vertical bar under the Home menu item.

In the menu icon anchor element, there is the attribute, " href='javascript:void(0);' " . This attribute is there, so that when the menu icon is clicked, no new webpage or section of the current webpage should be opened. The anchor element has an onclick event that calls a JavaScript function; see details below.

When the webpage is just open at the browser, the user sees the first three hyperlinks, the button with content name, "Dropdown" and the icon by its side, and then the About hyperlink. If the mouse pointer goes over the button, the drop-down list will appear, with the hyperlinks: Link 1, Link 2 and Link 3, vertically.

Note that the content of the button element is "Dropdown <i class='fa fa-caret-down'></i>" . The first part of the content is the text, "Dropdown ". The second part is the i element, "<i class='fa fa-caret-down'></i>" . It should interest the reader that this i element does not have any content. It should not have, for this case! The i element is actually the icon, that is twisted into an image. The class-name for the i element is 'fa fa-caret-down' . 'fa' refers to a CSS rule in the imported font-awesome/4.7.0 library. 'fa-caret-down' refers to another CSS rule in the imported font-awesome/4.7.0 library. The two rules twist the i element into an image (icon).

Strategy

There are three main tasks in this project. The first is to have all the menu items, with their heavy styling, in one assembly, when viewed. This needs the "overflow: hidden;" property for the outermost div (div.topnav) CSS rule.

The second main task is to have a drop-down menu. This is achieved by giving the innermost menu div (div.dropdown-content) that has the dropdown hyperlinks, the absolute position property and a z-index value of 1, assuming that the body element and its other elements have a z-index of 0. With that, when the dropdown menu appears, it will cover some of the content in the body element. When it is not displayed, it has a display property of none. In order to have it displayed, give it a display property of block (override), for button on-hover.

The third main task concerns small device screens (responsiveness). When the screen is small, and the menu items are vertical, the dropdown menu (innermost div) should appear, pushing down the other menu items below it, and not cover (be in front of) them. To achieve this, the absolute position property and the z-index property, of the innermost div have to be removed. This is done by having a whole media screen query (to override). In fact, there are actually two media screen queries in this project; see below for details.

The HTML style Element Content

With the exception of the div for the main document, having the attribute, "style='padding-left:16px' ", all the styles are coded within the start and end tags of the HTML style element.

Styling the Body Element

The CSS rule for the body element is:

            body {
                margin:0;font-family:Arial
            }

The margin for the four sides of the body element is 0. With that, the left edge of the bar (whether horizontal or vertical) will align with the left edge of the body element. The top edge of the bar (whether horizontal or vertical) will align with the top edge of the body element. The right edge of the bar (whether horizontal or vertical) will align with the right edge of the body element.

The font to use for all the elements in the body, is Arial.

Styling the Outermost div

The CSS rule for the outermost div is:

            div.topnav {
                overflow: hidden;
                background-color: #333;
            }

The background color of this bar is #333 (rather black).

If the property and value, "overflow: hidden;" is absent, then all the elements in the div.topnav, with their heavy styling, will not be held in one assembly, when viewed.

Styling the Anchor elements for wide Screens

Remember that the code for the hyperlink is the anchor element. The CSS rule for all the anchor elements, including the dropdown anchor elements is:

            div.topnav a {
                float: left;
                font-size: 17px;
                color: #f2f2f2;
                text-align: center;
                padding: 14px 16px;
                text-decoration: none;
            }

All the anchor elements, including the great grand children anchor elements (drop-down hyperlinks), are floated left. At this point, it is assumed that the reader knows the use of the rest of the properties in the CSS rule.

Styling the Inner div

The HTML inner div has the class-name, "dropdown" . The first element of this inner div is the button. The second element is the innermost div, that has the drop-down anchor elements. The CSS rule for the inner div is:

            div.dropdown {
                float: left;
            }

The inner div and all its content is floated left. Conception of the dropdown menu begins from this inner div.

Styling the button

The CSS rule for the button is:

            div.dropdown button.dropbtn {
                font-size: 17px;   
                border: none;
                margin: 0;
                color: white; 
                padding: 14px 16px;
                background-color: inherit;
                font-family: inherit;
            }

The border is none, so that the button fits into the horizontal bar like the preceding hyperlinks. The background color of the button is the background color of its parent container: inherited. The font-family for the button text, is the font-family for the parent container: inherited. At this point, it is assumed that the reader knows the use of the rest of the properties in the CSS rule.

Styling the Innermost div

The innermost div whose class-name is "dropdown-content", has the dropdown hyperlinks. It is the menu div. The CSS rule for the innermost div is:

            div.dropdown-content {
                display: none;
                position: absolute;
                z-index: 1;
                width: 160px;
                background-color: #f9f9f9;
            }

When the mouse pointer is not over the button, actually not over the inner div, which has the same size as the button at that time, the display of the innermost menu div is none. This means that it has not appeared. In order for the innermost menu div to appear, this display property has to be made, block. When it appears, it will have to cover (be in front of) the content below the button. So it needs the absolute position property, and a z-index of 1, assuming that the body and its other elements are at a z-index of 0. The width of the inner menu div is 160px and its background color is #f9f9f9 (very light gray).

The innermost menu div should appear just below the button, as was coded.

Outermost Horizontal Hyperlinks On-hover, and Button On-hover

When the mouse pointer goes over the outermost hyperlinks in the horizontal bar or over the button, the background color of the hyperlinks or the background color of the button, becomes #555 (grayish). The color of text becomes white. The CSS rule for the two cases is:

            div.topnav a:hover, div.dropdown:hover button.dropbtn {
                background-color: #555;
                color: white;
            }

Note the use of the comma, in the selector.

Styling the Dropdown Anchor Elements

For this project, there are only three dropdown anchor elements, and they are all in the innermost menu div. Their styling has some differences with the outermost hyperlinks in the horizontal div. There is a CSS rule dedicated to them, where some properties override those for the outermost anchor elements in the horizontal bar. The CSS rule for the anchor elements in the innermost menu div is:

            div.dropdown-content a {
                display: block;
                float: none;
                color: black;
                padding: 12px 16px;
                text-align: left;
            }

Anchor elements are normally inline elements and would appear in a horizontal line, when typed next to one another. By giving the value of block, to the display property, all the anchor elements will appear one below the other, making a vertical presentation. The color of text is black, overriding the white color for the other anchor elements. The padding is "12px 16px;". Text within an anchor element is 'left-align', overriding 'center' for the other hyperlinks. The text is not underlined (inherited from the "div.topnav a" CSS rule).

Making the Innermost Menu div Appear

When the mouse pointer goes over the button, actually over the inner div, whose class-name is "dropdown", in order for the inner div to appear, its display property has to be made block. The CSS rule for that is:

            div.dropdown:hover div.dropdown-content {
                display: block;
            }

When the value of the display property of the innermost menu div (div.dropdown-content) is none, the innermost menu div is not shown. On-hover, this CSS rule overrides that property and makes it block; then the innermost menu div appears.

The first expression, "div.dropdown:hover" in the selector, is for when the mouse pointer goes over the inner div, whose size at that time is the same as that of the button. The inner div always has the button as one of its contents. The inner div extends downwards, when the innermost menu div appears.

The display property (display: block;) in the CSS rule, applies to the innermost menu div (div.dropdown-content), and not to the inner div (dropdown). What concerns the inner div in the selector, is the pseudo class, ":hover".

The Dropdown Anchor Elements On-hover

All the dropdown anchor elements for this project are in the innermost menu div. The CSS rule for that is:

            div.dropdown-content a:hover {
                background-color: #ddd;
                color: black;
            }

The background color becomes #ddd (grayish), when the mouse pointer goes over a dropdown hyperlink (anchor element). The color of text becomes black.

The Menu Icon

The menu icon with code, "☰" is the last outermost hyperlink. It is styled to be at the end of the first line, whether the menu is horizontal or vertical. For wide screens the menu icon is not displayed. For small screens, it is displayed. The CSS rule is:

            div.topnav a.icon {
                display: none;
            }

This rule applies to wide screens. For small screens, the display is made inline (viewable).

Media Screen Queries

When the device screen width is less than or equal to 600px, the menu icon would appear at the right end of the shortened horizontal bar; and only the first hyperlink (Home) will be in the shortened horizontal bar, and at the left end. The media screen query for that is:

            @media screen and (max-width: 600px) {
                div.topnav a:not(:first-child), div.dropdown button.dropbtn {
                    display: none;
                }
                div.topnav a.icon {
                    float: right;
                    display: inline;
                }
            }

The class-name for the menu icon hyperlink in the body element is "icon".

Changes to Properties for Small Screens

The value of the display property of all the outermost anchor elements and the button, except the icon hyperlink, has to be made none, so that they cannot be seen, as soon as a small device screen is encountered.

For a wide screen, all hyperlinks were floated to the left and the display property for the menu icon hyperlink was made none (so that it could not be seen). For a small screen, the menu icon alone has to be floated to the right and the value of its display property has to be inline, so that it can be seen.

It should be noted, that when a small screen is encountered, the above media screen query, hides the all the anchor elements except the first and the menu icon hyperlink; and the menu icon element is flushed to the right.

CSS Requirements for the Vertical Bar

There is another longer media screen query for the other changes as follows:

When the menu icon is clicked to change the horizontal bar into a vertical bar, the first anchor element (Home) will take the whole first line of the new vertical bar. With that alone, there would be no place for the menu icon. The solution is to have the menu icon remain at its position, but in front of the line of the Home hyperlink. In order to achieve that, a new class is needed. The name given to this class is, responsive. The responsive class will only exists in memory; it is not hard coded as class-name for any element in the HTML body element.

The responsive class is given the position, relative, because its child element, the menu icon, is given the absolute position property (since it will be in front). In this new state, the distance from the right end of the Home hyperlink to the right end of the menu icon, will be 0px; and the distance from the top end of the Home hyperlink to the top end of the menu icon will also be 0px.

For the wide screen, all the outermost anchor elements were floated left; now, the value of their float property is none. For the wide screen, all the outermost anchor elements were inline; now, the value of their display property is block, so that they are presented vertically, one below the other (and from the left end of the vertical bar to the right end of the vertical bar). For the wide screen, all the outermost anchor elements had their text horizontally centered within the rectangle of the hyperlink; now, the value of their text-align property is left. One CSS rule in the second media screen query, takes care of the three properties mentioned in this paragraph.

For the wide screen, the inner div (div.dropdown) was floated left, along with the hyperlinks, for consistency; now, the value of its float property is none.

The innermost div (div.dropdown-content) has to be given the relative position property, so that its content will push down the lower content of the new vertical bar, otherwise, its content may even go behind the lower content. This is a special use of the relative position property.

For the wide screen, the button element was inline by default; now, the value of its display property is block, so that it fits vertically with the outermost hyperlinks. The button is now given a 100% width, so that it extends from the left end of the vertical bar to the right end of the vertical bar. The text within its rectangle is now left aligned, for consistency with the outermost hyperlinks (now left-aligned) in the vertical bar. The second media screen query is:

            @media screen and (max-width: 600px) {
                div.topnav.responsive {
                    position: relative;
                }
                div.topnav.responsive a.icon {
                    position: absolute;
                    right: 0;
                    top: 0;
                }
                div.topnav.responsive a {
                    float: none;
                    display: block;
                    text-align: left;
                }
                div.topnav.responsive div.dropdown {
                    float: none;
                }
                div.topnav.responsive div.dropdown-content {
                    position: relative;
                }
                div.topnav.responsive div.dropdown button.dropbtn {
                    display: block;
                    width: 100%;
                    text-align: left;
                }
            }

Note that there has been no CSS rule to define the responsive class. The expression, ".responsive" has just been attached to the right end of the expression, "div.topnav", for the above six CSS rules.

JavaScript

As soon as a small screen is encountered, the first media screen query above takes effect. There is no vertical bar yet. However, the all the outermost hyperlinks except the first are hidden. The menu icon appears on the right of the shortened horizontal bar. The Home hyperlink remains alone on the left.

When the menu icon is clicked, JavaScript converts the shortened horizontal bar to a vertical bar, where the first outermost hyperlink of the horizontal bar becomes the first element of the vertical bar. JavaScript uses the new memory responsive class to change the horizontal menu to a vertical menu. Note that the new memory responsive class is associated only with the second media query above. The JavaScript is:

        <script type="text/javascript">
            function myFunction() {
                var x = document.getElementById("myTopnav");
                if (x.className === "topnav") {
                    x.className += " responsive";
                } else {
                    x.className = "topnav";
                }
            }
        </script>

The whole script is just one main function, myFunction(). In the HTML body element, the menu icon hyperlink has the onclick event, "onclick='myFunction()' " . When the menu icon is clicked, the function is called. If the class-name of the outermost div is "div.topnav" and not "topnav responsive", then the class-name " responsive" is joined with the class-name "topnav" to form "topnav responsive". With that, the "responsive" class-name takes precedence, in the sense that for any common CSS property in both classes, the value of that for the "responsive" class-name, overrides that for the "topnav". Also, new CSS properties in "responsive" become effective.

On the other hand, if the class-name is "topnav responsive" and not "topnav", then the class-name becomes "topnav" for the horizontal shortened bar of the first media screen query.

The Complete Webpage Code

And there you have it: the complete webpage code is:

    <!DOCTYPE html>
    <html>
    <head>
        <title>Responsive Topnav with Dropdown</title>
        <link rel='icon' href='https://www.examplee.com/images/logo.jpg' type='image/x-icon'>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="Description of the Web Page.">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

        <style>
            body {
                margin:0;font-family:Arial
            }

            div.topnav {
                overflow: hidden;
                background-color: #333;
            }

            div.topnav a {
                float: left;
                font-size: 17px;
                color: #f2f2f2;
                text-align: center;
                padding: 14px 16px;
                text-decoration: none;
            }

            div.dropdown {
                float: left;
            }

            div.dropdown button.dropbtn {
                font-size: 17px;   
                border: none;
                margin: 0;
                color: white; 
                padding: 14px 16px;
                background-color: inherit;
                font-family: inherit;
            }

            div.dropdown-content {
                display: none;
                position: absolute;
                z-index: 1;
                width: 160px;
                background-color: #f9f9f9;
            }
            
            div.topnav a:hover, div.dropdown:hover button.dropbtn {
                background-color: #555;
                color: white;
            }

            div.dropdown-content a {
                display: block;
                float: none;
                color: black;
                padding: 12px 16px;
                text-align: left;
            }
            
            div.dropdown:hover div.dropdown-content {
                display: block;
            }

            div.dropdown-content a:hover {
                background-color: #ddd;
                color: black;
            }
            
            div.topnav a.icon {
                display: none;
            }

            div.topnav a.active {
                background-color: #04AA6D;
                color: white;
            }
            
            @media screen and (max-width: 600px) {
                div.topnav a:not(:first-child), div.dropdown button.dropbtn {
                    display: none;
                }
                div.topnav a.icon {
                    float: right;
                    display: inline;
                }
            }
            
            @media screen and (max-width: 600px) {
                div.topnav.responsive {
                    position: relative;
                }
                div.topnav.responsive a.icon {
                    position: absolute;
                    right: 0;
                    top: 0;
                }
                div.topnav.responsive a {
                    float: none;
                    display: block;
                    text-align: left;
                }
                div.topnav.responsive div.dropdown {
                    float: none;
                }
                div.topnav.responsive div.dropdown-content {
                    position: relative;
                }
                div.topnav.responsive div.dropdown button.dropbtn {
                    display: block;
                    width: 100%;
                    text-align: left;
                }
            }
        </style>

        <script type="text/javascript">
            function myFunction() {
                var x = document.getElementById("myTopnav");
                if (x.className === "topnav") {
                    x.className += " responsive";
                } else {
                    x.className = "topnav";
                }
            }
        </script>
    </head>
    <body>
        <div class="topnav" id="myTopnav">
            <a href="#home" class="active">Home</a>
            <a href="#news">News</a>
            <a href="#contact">Contact</a>
            <div class="dropdown">
                <button class="dropbtn">Dropdown <i class="fa fa-caret-down"></i></button>
                <div class="dropdown-content">
                    <a href="#">Link 1</a>
                    <a href="#">Link 2</a>
                    <a href="#">Link 3</a>
                </div>
            </div> 
            <a href="#about">About</a>
            <a href="javascript:void(0);" style="font-size:15px;" class="icon" onclick="myFunction()">☰</a>
        </div>

        <div style="padding-left:16px">
            <h2>Responsive Topnav with Dropdown</h2>
            <p>Resize the browser window to see how it works.</p>
            <p>Hover over the dropdown button to open the dropdown menu.</p>
        </div>
    </body>
    </html>

The reader should copy the complete code into a text editor. Save the file with any name, but with the extension, .html . Open the saved file in the browser. Hover over the button to see the dropdown menu. Next, reduce the width of the webpage continuously, until the menu icon appears. Click the menu icon, to see the horizontal menu bar develop into a vertical menu bar. Hover over the button again to see the same behavior of the dropdown menu.

Chrys





Related Links:

More Related Links:

Cousins

Menus

How to Create a Menu Icon with HTML and CSS and without using a Library
How To Create a Top Navigation Bar
How to Create Fixed Auto Height Sidebar Menu with CSS
How to Create a Horizontal Tabs Bar with their Sections using CSS and JavaScript
How to Create a Search Menu to Filter List Items, using CSS and JavaScript
How To Create a Responsive Top Navigation Bar with Left-aligned and Right-aligned Hyperlinks
How to Create a Top Fixed Horizontal Menu with CSS
How to Create a Vertical Navigation Menu for Smartphones and Tablets Using CSS and JavaScript
How to Create a Slide Down Full Screen Curtain Navigation Menu
How To Create a Responsive Collapsible Sidebar Menu
How to Create Pagination of Numbers with Borders
How to Create a Narrow Sticky Vertical Sidebar for Different Social Media Icons
How to Create a Vertical HTML Button Group with CSS
How To Create a Breadcrumb Navigation Menu
How to Create a Hover-able Dropup Menu with CSS Only
How to Create a Clickable Dropdown Menu with CSS and JavaScript
How to Create a Clickable Dropdown Menu inside a Responsive Navigation Sidebar with CSS and JavaScript
How to Create a Hover-able Dropdown Menu inside a Responsive Horizontal Navigation Bar with CSS and JavaScript
How to Create a Clickable Dropdown Broad Menu inside a Horizontal Navigation Bar using CSS and JavaScript

Images

Coming soon . . .

Buttons

Coming soon . . .

Forms

Coming soon . . .

Filters

Coming soon . . .

Tables

Coming soon . . .
BACK NEXT

Comments