S

Simple CSS only, animated dropdown navigation

Found on every website, the navigation is one of their core elements. It is responsible for a mayor part of the user experience. The more complex a web project is, the more items need to be included in the main menu. Not only for better usability, but also to offer a clean structure to the visitor, we usually nest the items into logical hierarchies for related topics. One of the most used design schemes to display those hierarchies is a dropdown menu. In this short tutorial I will show you how to create such a menu using just HTML and CSS.

Note: This is a beginners tutorial, so we I will only focus on the main topic, that is to create the dropdown navigation and the corresponsig styling and HTML elements. Font styling and other properties will not be covered. Please be aware, that this is not yet a responsive solution as well. But it will work in all modern browsers.

First navigaton level

We start off simple with the first level of the menu. Normally we structure navigation items using the «ul» HTML tags. this helps us to understand the hierarchy easily. Furthermore it allows the text elements to be structured in more than one level. Since we need to interact with the single elements to open other sites we use the «a» tag, so we can add hyperlinks (For this example we will not add any href attributes).

<ul class="my-menu">
 <li class="my-menu-current">
  <a>Home</a>
 </li>
 <li>
  <a>Products</a>
 </li>
 <li>
  <a>About us</a>
 </li>
 <li>
  <a>Blog</a>
 </li>
</ul>

By using the class «my-menu» we can now access any of the containers directly. Let’s start with styling the ul element and resetting the default layout of this tag. For the «li» items to be aligned horizontally, we make use of css flex boxes.

.my-menu{
 display: flex; /* Define as a flex element */
 position: relative; /* Allows us to use z-index */
 list-style: none; /* Reset the default list layout */
 width: 100%;
 padding: 0;
 margin: 0;
 background-color: #224A59;
 z-index: 10; /* Makes the menu overlap items existing later in the DOM */
}

The next step would be to style the link elements themselves. We firstly format the «a» block elements, since a normal «a» tag is a inline tag by default. The inline element wouldn’t allow us to use certain properties, such as padding for example.

To highlight the current menu item and add some spice to the mouseover interaction we make use of the «my-menu-current» class and the «hover» pseudo selector. We smoothen out the style change by implementing the «transition» property on the «a» element.

.my-menu > li > a{
 display: block;
 padding: 12px 24px;
 color: #fff;
 text-decoration: none;
 cursor: pointer;
 transition: all .3s ease-in-out;
}

.my-menu > li > a:hover,
.my-menu > li.my-menu-current > a{
 background-color: rgba(0,0,0,.2);
}

Note: As you most certainly noticed we use selectors using the «>» operator. This operator says that only items which inherit immediately from the selector defined directly before the operator should be addressed. This is not necessairy, but prevents us to have to override those properties on deeper hierarchy levels. For better understanding we do not want to override anything in this tutorial, but style every level by itself.

After adding all those styles, the first level of the menu now looks as followed.

Preview

Adding some sub-menus

Right until now we had pretty basic stuff. So let’s start to add some complexity to it. We will add some sub-menus to certain menu items by implementing another ul element, containing the child elements to those items. For easier access we give them a new class called «my-sub-menu»

<ul class="my-menu">
 <li class="my-menu-current">
  <a>Home</a>
 </li>
 <li>
  <a>Products</a>
  <ul class="my-sub-menu">
   <li><a>Product 1</a></li>
   <li><a>Product 2</a></li>
   <li><a>Product 3</a></li>
   <li><a>Product 4</a></li>
  </ul>
 </li>
 <li>
  <a>About us</a>
  <ul class="my-sub-menu">
   <li><a>Team</a></li>
   <li><a>History</a></li>
   <li><a>Location</a></li>
  </ul>
 </li>
 <li>
  <a>Blog</a>
 </li>
</ul>

Now that the new Elements are added, we can start styling them. But first there is a small preparation we have to do for the parent «li» elements. Since the child elements need to be overlapping with other HTML elements and not interact with their surounding elements, we need to position them absolute. The problem is, that an absolute position element needs the parent element to be positioned as well (to not have «position:static»), so properties like top, right, bottom and left are relative to the parent. Otherwise it goes up in the DOM until it finds a positioned container to use as reference, stopping at the body container. So in a nutshell we make the parent «li» items relative positioned.

.my-menu > li{
 position: relative;
}

As mentioned before, the childs need to be positioned «absolute». By using the top and left property we now can position the childs relative to their corresponding «li» parents. Apart from the positioning we also add some styles to make the sub-menus look nice.

.my-sub-menu{
 position: absolute;
 top: 100%;
 left: 0;
 list-style: none;
 padding: 0;
 background-color: rgba(0,0,0,.9);
}

Like within the first level, we now can style the «a» elements for sub-menus as well.

.my-sub-menu > li > a{
 display: block;
 width: 180px;
 padding: 4px 24px;
 color: #fff;
 text-decoration: none;
 cursor: pointer;
}

The menu is now in a static state in which the submenus are always visible and overlapping each other. It isn’t pretty, but the base from which we can make it more interactive and add the desired dropdown effect.

Preview

Finish it up with transformations

The last part of this process is to add the actual dropdown effect itself. For this we will make use of the CSS «transform» property. This allows the container on which it is applied to, to transform itself within 3 Dimensional space. By scaling the my-sub-menu container vertically to 0%, we can hide the container if no mouseover on its parent element occurs. To save some code we will also make use of the «:not» pseudo selector. This way we only have to manipulate the appearance if no mouseover is made and make the visible state default.

.my-sub-menu{
  ... /* Previous code from above */
 transform-origin: top left; /* Set the transformation start point */
 transition: all .2s ease-in-out; /* Animate the dropdown movement */
}

.my-menu > li:not(:hover) > .my-sub-menu{
 transform: scaleY(0);
}

So thats about it. As you can see below, we created a simple and smooth dropdown navigation with two levels.

Preview

Useful links

https://developer.mozilla.org/de/docs/Learn/CSS/CSS_layout/Flexbox (Mozilla Flexbox documentation)
https://developer.mozilla.org/de/docs/Web/CSS/transform (Mozilla «transform» documentation)
https://developer.mozilla.org/de/docs/Web/CSS/position (Mozilla «position» documentation)
https://developer.mozilla.org/de/docs/Web/CSS/:not (Mozilla «:not» documentation)

Comments

0 Comments