Friday 11 June 2021

Web Tutorial: The Navigational Menu

Drop-down navigation menus have been around for a very long time. They're a staple of website navigation, even in the age of smartphones. Back when I first started out in web development, I tended to think drop-down menus were accomplished using a mixture of HTML and JavaScript. The end result was that my menus were often computationally expensive and didn't work if JavaScript was turned off.

A couple years of experience later and much training on CSS later, I learned to create these menus using only HTML and CSS. It's pretty elementary; all that's really needed is a decent working knowledge of the "cascading" part of CSS. And maybe some understanding of the differences between inline and block elements.

Without further ado...

Here's some HTML. There are a few blocks of Lorem Ipsum text in the body, within the div styled using CSS class content.
<!DOCTYPE html>
<html>
    <head>
        <title>Navigational Bar Demo</title>
    </head>

    <style>

    </style>

    <body>
        <div class="content">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras risus massa, aliquet non justo non, convallis tincidunt purus. Integer dolor purus, facilisis dapibus metus id, blandit dignissim lorem. Pellentesque ut lobortis nisi. Cras viverra nisi sed ligula vulputate varius. Vestibulum mi nisi, placerat sit amet mollis id, consectetur malesuada sem. Etiam vitae tellus in libero sodales convallis. Aliquam erat volutpat. Sed vel libero in orci pharetra cursus. Nulla sit amet congue lectus. Pellentesque suscipit turpis non urna accumsan pulvinar. Pellentesque luctus dui cursus lorem pharetra, a hendrerit massa congue. Donec lacinia iaculis enim in placerat. Sed dictum scelerisque massa ac sagittis. Pellentesque mattis mi non felis porta tempus. Vivamus nec ex semper, euismod ligula nec, mattis nibh. </p>

            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut consectetur erat orci, et elementum augue facilisis et. Nullam ligula lacus, dapibus vitae odio a, mollis tempus enim. Donec ut nunc tristique, semper massa vel, faucibus ipsum. Quisque est eros, varius sed placerat sollicitudin, eleifend in nunc. In auctor nisl sapien, sit amet tincidunt massa mollis sed. Suspendisse potenti. Duis egestas pellentesque velit id bibendum. Vestibulum varius bibendum felis ac fringilla. Donec justo mauris, posuere sit amet risus eu, cursus faucibus leo. Proin a ante sollicitudin, fermentum urna porttitor, ultrices neque.</p>

            <p>Cras massa massa, ultricies quis condimentum eu, accumsan ut est. Donec at maximus eros, vitae vulputate orci. Nam quis neque ac velit molestie volutpat id eu libero. In ullamcorper nisl eu arcu vestibulum, at venenatis libero fermentum. Proin ac sem pellentesque, vestibulum purus non, molestie turpis. In vel eleifend ipsum. In ligula dolor, sollicitudin eu bibendum et, varius a enim. Nulla tincidunt leo in ante semper laoreet. Sed lectus ex, rutrum sed consequat ut, molestie tempor elit. </p>

            <p>Pellentesque mauris ligula, suscipit malesuada risus at, posuere ultrices tellus. Nulla nec eros non ex ullamcorper tincidunt nec sed nulla. Fusce bibendum mi id dolor pretium, ac rhoncus magna viverra. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Integer lacus sapien, consequat ultricies consectetur ac, viverra a neque. Interdum et malesuada fames ac ante ipsum primis in faucibus. Morbi aliquam eget tortor ut elementum. Maecenas commodo lorem mauris.</p>

            <p>Maecenas quis nunc id diam finibus ornare efficitur non orci. Quisque id ultricies risus. Morbi vitae elit pharetra, sollicitudin eros euismod, aliquam est. Ut sit amet libero tempor, auctor nulla vitae, pulvinar justo. Mauris ornare laoreet nisi, sit amet semper nibh accumsan sed. In id justo rhoncus, consectetur enim et, gravida purus. Sed vitae pellentesque urna. Pellentesque pretium, enim non scelerisque consequat, augue odio tempor felis, in laoreet leo massa vel diam. </p>
        </div>
    </body>
</html>


Take a look right now; this is your bare bones page without styling and navigation.


Now add a nav tag.
<body>
    <nav>
    </nav>

    
    <div class="content">


And let's do some styling. Let's do the body.
<style>
    body
    {
        font-size: 14px;
        font-family: arial;
        margin: 0px;
        padding: 0px;
    }

</style>


Next, we style content. It should have a margin from the top, to make way for the navigation bar.
<style>
    body
    {
        font-size: 14px;
        font-family: arial;
        margin: 0px;
        padding: 0px;
    }

    .content
    {
        padding: 1em;
        margin-top: 5em;
    }
</style>


And then we style the nav tag. Yep, this is totally HTML5. I am going to default to my go-to color; namely, shades of orange and yellow. This will be the background color. We set the  position property to absolute and the left and top properties so that the menu bar is affixed to the top of the page. width and height is defined such that the navigation bar will fill up a thin horizontal stripe.
body
{
    font-size: 14px;
    font-family: arial;
    margin: 0px;
    padding: 0px;
}

nav
{
    width: 100%;
    height: 45px;
    background-color: rgba(255, 150, 0, 1);
    padding: 0.5em;
    position: absolute;
    top: 0;
    left: 0;
}


.content
{
    padding: 1em;
    margin-top: 5em;
}


See what we did there? This is a good beginning.


The First Level

All right! Let's begin filling in the navigation bar with the first level. We will first use a ul tag to make an unordered list.
<nav>
    <ul>

    </ul>

</nav>


Then let's have a few li tags, or list items, in there.
<nav>
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>

    </ul>
</nav>


Each of these items will be clickable, so we use anchor tags in there.
<nav>
    <ul>
        <li><a href=""></a></li>
        <li><a href=""></a></li>
        <li><a href=""></a></li>
        <li><a href=""></a></li>
    </ul>
</nav>


And here's the text. For simplicity and obvious visibility, I will name them as such.
<nav>
    <ul>
        <li><a href="">Menu Level 1 item 1</a></li>
        <li><a href="">Menu Level 1 item 2</a></li>
        <li><a href="">Menu Level 1 item 3</a></li>
        <li><a href="">Menu Level 1 item 4</a></li>
    </ul>
</nav>


What you are seeing is the default look of unordered lists and list items. In order for them to behave like a menu bar, some styling is needed.


Firstly, we need to set each li tag in the nav element. The display property is set to inline-block, because we want this to behave like an inline element, yet we also want to set width and float properties. This is very important!
nav
{
    width: 100%;
    height: 45px;
    background-color: rgba(255, 150, 0, 1);
    padding: 0.5em;
    position: absolute;
    top: 0;
    left: 0;
}

nav ul li
{
    display: inline-block;
    width: 200px;
    float: left;
}


.content
{
    padding: 1em;
    margin-top: 5em;
}


Ah, now you can see it all lines up nicely!


Since we're at it, let's style the anchor tags here to be a bit more presentable. I've gone with white bold Verdana text, and set it not to display the underline, by giving the text-decoration property the value none.
nav ul li
{
    display: inline-block;
    width: 200px;
    float: left;
}

nav ul li a
{
    color: rgba(255, 255, 255, 1);
    font-weight: bold;
    font-family: verdana;
    text-decoration: none;        
}


nav ul li a:hover
{
    text-decoration: none;
}


.content
{
    padding: 1em;
    margin-top: 5em;
}


Looking good.


The Second Level

Now, what we want is for the second-level menu to appear when we mouse over the appropriate navigation bar item. No fancy animations, just the basics.

To have a second-level menu, we nest another unordered list and list items in any one (or two, in this case) of the main unordered list. For those items that have the second-level menu, I've added this ▼ to indicate such.
<ul>
    <li><a href="">Menu Level 1 item 1</a></li>
    <li>
        <a href="">Menu Level 1 item 2 &#9660;</a>
        <ul>
            <li><a href="">Menu Level 2 item 1</a></li>
            <li><a href="">Menu Level 2 item 2</a></li>
        </ul>

    </li>
    <li>
        <a href="">Menu Level 1 item 3 &#9660;</a>
        <ul>
            <li><a href="">Menu Level 2 item 1</a></li>
            <li><a href="">Menu Level 2 item 2</a></li>
        </ul>

    </li>
    <li><a href="">Menu Level 1 item 4</a></li>
</ul>


This is all you will see at this point. More styling is needed.


We first add this to ensure that all second-level menus are hidden.
nav ul li a:hover
{
    text-decoration: none;
}

nav ul li ul li
{
    display: none;
}


.content
{
    padding: 1em;
    margin-top: 5em;
}


Then we add some hover behavior to ensure that the second-level menu takes on these properties when its parent is moused over.
nav ul li ul li
{
    display: none;
}

nav ul li:hover ul
{
    width: 200px;
    float: left;
    margin-left: -3em;
    margin-top: 1.5em;
}


.content
{
    padding: 1em;
    margin-top: 5em;
}


More hover behavior on the parent, but this time it's the list item that is affected. At this point, the display property should now be inline-block. The padding and height is up to individual preference. float is set to left, which will ensure that the display is vertical because width is 100% of its parent, so each item will leave no space for the next item, thus forcing it to the next line. Background color has been set to orange as well, with a translucent white bottom border.
nav ul li:hover ul
{
    width: 200px;
    float: left;
    margin-left: -3em;
    margin-top: 1.5em;
}

nav ul li:hover ul li
{
    display: inline-block;
    padding: 1em 0.5em 0.5em 0.5em;
    width: 100%;
    height: 30px;
    float: left;
    background-color: rgba(255, 150, 0, 1);
    border-bottom: 1px solid rgba(255, 255, 255, 0.5);
}


.content
{
    padding: 1em;
    margin-top: 5em;
}


And now this is what happens when you mouse over! No need to set styling for the anchor tags unless you want a different look; they inherit their look from the parent.


Add this hover behavior to ensure that background color changes (I chose a nice yellow) when you mouse over the list item.
nav ul li:hover ul li
{
    display: inline-block;
    padding: 1em 0.5em 0.5em 0.5em;
    width: 100%;
    height: 30px;
    float: left;
    background-color: rgba(255, 150, 0, 1);
    border-bottom: 1px solid rgba(255, 255, 255, 0.5);
}

nav ul li ul li:hover
{
    background-color: rgba(255, 200, 0, 1);
}


.content
{
    padding: 1em;
    margin-top: 5em;
}


Yep! That's your second-level menu, right there.



The Third Level

Now I don't usually advocate for a third-level menu (much less a fourth) because it's a poor practice and should really be avoided. But what if you had to make one?

In those cases, more nesting would be needed. Let's use the third item of the main menu as an example. Nest another unordered list within second-level items 2 and 3, with more list items.
<nav>
    <ul>
        <li><a href="">Menu Level 1 item 1</a></li>
        <li>
            <a href="">Menu Level 1 item 2 &#9660;</a>
            <ul>
                <li><a href="">Menu Level 2 item 1</a></li>
                <li><a href="">Menu Level 2 item 2</a></li>
            </ul>
        </li>
        <li>
            <a href="">Menu Level 1 item 3 &#9660;</a>
            <ul>
                <li><a href="">Menu Level 2 item 1</a></li>
                <li>
                    <a href="">Menu Level 2 item 2 &#9654;</a>
                    <ul>
                        <li><a href="">Menu Level 3 item 1</a></li>
                        <li><a href="">Menu Level 3 item 2</a></li>
                    </ul>

                </li>
                <li>
                    <a href="">Menu Level 2 item 3 &#9654;</a>
                    <ul>
                        <li><a href="">Menu Level 3 item 1</a></li>
                        <li><a href="">Menu Level 3 item 2</a></li>
                    </ul>

                </li>
                <li><a href="">Menu Level 2 item 4</a></li>
            </ul>
        </li>
        <li><a href="">Menu Level 1 item 4</a></li>
    </ul>
</nav>


You see where this is going? Now I use the ▶ instead to show that this submenu item has more submenu items. But wait... the third-level items aren't supposed to appear yet. Let's fix this.


When a second-leven menu item is moused over, the overflow property of nested list items should be set to hidden.
nav ul li:hover ul li
{
    display: inline-block;
    padding: 1em 0.5em 0.5em 0.5em;
    width: 100%;
    height: 30px;
    float: left;
    background-color: rgba(255, 150, 0, 1);
    overflow: hidden;
    border-bottom: 1px solid rgba(255, 255, 255, 0.5);
}


Nice and neat!


Then we ensure the overflow property is set to visible when mousing over child list items.
nav ul li ul li:hover
{
    background-color: rgba(255, 200, 0, 1);
    overflow: visible;
}


And here we add this so that the ul tags under all these moused-over submenu items, have margin-top property set. This just aligns the element nicely; feel free to leave it out and see what happens.
nav ul li ul li:hover
{
    background-color: rgba(255, 200, 0, 1);
    overflow: visible;
}

nav ul li ul li:hover ul
{
    margin-top: -2.5em;
}


.content
{
    padding: 1em;
    margin-top: 5em;
}


Remember what we did for the second-level menu items? This is more of the same.
nav ul li ul li:hover ul
{
    margin-top: -2.5em;
}

nav ul li ul li ul li
{
    display: inline-block;
    padding: 0.5em;
    width: 100%;
    height: 30px;
    margin-left: 209px;
}


.content
{
    padding: 1em;
    margin-top: 5em;
}


There it is!


No more styling is needed. When you mouse over the third-level menu items, they will turn yellow, having inherited the properties of their parent.

Nav-er say nav-er!
T___T

No comments:

Post a Comment