How to Create a Responsive Website Header - Part 3
In this detailed web development tutorial, I'll teach you how to create a responsive website header with dropdown subnavigation menus using HTML, CSS, and JavaScript.
This article, which is part 3 of a 5-part series of Web Development tutorials, will guide you through the process of creating a website header. We'll use HTML, CSS, and JavaScript to construct a header layout with two Subnavigation Menus that open and close as needed. In this example, we'll examine a complete web page demonstration before taking a detailed look at the concepts and code that bring it to life.
This article builds upon topics discussed in How to Create a Responsive Website Layout.
In this article, we'll use our standard HTML Document Structure and CSS Naming Convention.
Skip Ahead
Looking for something specific? Select a topic in this article to read more:
Subnavigation Menus
In this example, we'll build upon our Accordion Navigation Menu design to include two subnavigation menus that open and close as needed:
Subnavigation menus allow secondary navigation content to be added to the primary navigation content without increasing its initial size on the page. This design is well-suited for large websites with a lot of pages that can be organized into a hierarchy of categories. When a visitor selects a category, the subnavigation menu opens to show the list of pages included in that category. When a visitor deselects a category, the subnavigation menu closes to hide the list of pages included in that category.
On small screens, where the navigation menu items are displayed vertically, the subnavigation menus behave as accordions. On medium and large screens, where the navigation menu items are displayed horizontally, the subnavigation menus behave as dropdowns.
In this example, we'll create two subnavigation menus - one for a "Products" menu and one for a "Services" menu. But you can easily modify the code presented in this article to create as many categories as you like, and to include any content that is relevant to your website.
Header Structure and Style
First, we create our header area.
The construction of the header area is similar to our Accordion Navigation Menu design. But we add:
- CSS to allow the dropdown behavior
Let's start with the HTML used to create the header area for our responsive subnavigation menu design:
HTML
<!-- Header -->
<header class="header">
<!-- Title -->
...
<!-- Site Navigation -->
...
</header>
Here we create our header area using the
<header>
element and assign it:
-
The
class="header"
attribute to control the layout of the header area
Next the CSS:
CSS
* {
box-sizing: border-box;
margin: 0;
border: 0;
padding: 0;
}
body {position: relative;}
/* Page */
.page {
max-width: 640px;
margin: 0 auto;
}
@media (min-width: 960px) {
.page {max-width: 960px;}
}
/* Header */
.header {
font-size: 0;
text-align: center;
}
First, we create a CSS rule to control the default layout and style of all elements (unless otherwise specified). This rule applies the "border box" sizing model and resets margins, borders, and padding to 0.
Next we create a CSS rule to control the layout of the
body
element.
We include:
-
The
position: relative;
property to allow the subnavigation areas to be positioned relative to thebody
element
Then, we create the
.page
CSS rule to control the layout of our page areas so that:
- The maximum width is 640px on small and medium screens
- The maximum width is 960px on large screens
Finally, we create the
.header
CSS rule to control the layout of our header area.
We include:
-
The
font-size: 0;
property to prevent browsers from adding undesirable whitespace around and between the title heading and navigation menu items (font size is redefined later so that all text is rendered to the correct size)
Title Structure and Style
The first item inside the header area is our title area.
The construction of the title area is identical to our Accordion Navigation Menu design.
Let's start with the HTML used to create the title area for our responsive subnavigation menu design:
HTML
<!-- Title -->
<div class="title">
<div class="page title_container">
<h1 class="title_heading">
<a href="#home"
class="title_heading_link">
My Website</a></h1>
<button type="button"
onclick="navToggle()"
class="title_button">
<i class="title_button_icon fa fa-bars"></i></button>
</div>
</div>
First, we create our title area using the
<div>
element and assign it:
-
The
class="title"
attribute to control the style of the title area
Inside the title area we create our title container using the
<div>
element and assign it:
-
The
class="page title_container"
attribute to control the layout of the title container
The first item inside the title container is our title heading.
We create this item using the
<h1>
element and assign it:
-
The
class="title_heading"
attribute to control the style of the title heading
Inside the title heading we use the
<a>
element to create a title heading link that directs visitors to our home page when clicked.
We assign it:
-
The
href="#home"
attribute to specify the destination of the title heading link -
The
class="title_heading_link"
attribute to control the style of the title heading link
The second item inside the title container is the title button that opens and closes our accordion navigation menu on small screens.
We create this item using the
<button>
element and assign it:
-
The
onclick="navToggle()"
attribute to execute the JavaScript function that opens and closes the accordion navigation menu when clicked -
The
class="title_button"
attribute to control the layout and style of the title button
Inside the title button we create our title button icon using the
<i>
element and assign it:
-
The
class="title_button_icon fa fa-bars"
attribute to control the style of the title button icon
Next the CSS:
CSS
/* Title */
.title {background: #4040BF;}
.title_container {
position: relative;
padding: 0 56px;
}
.title_heading {
display: inline-block;
font: bold 24px / 1.5 sans-serif;
}
.title_heading_link {
display: block;
padding: 16px;
text-decoration: none;
color: #FFFFFF;
}
.title_button {
display: none;
width: 56px;
height: 68px;
position: absolute;
right: 0;
top: 0;
padding: 16px;
font: 24px / 1.5 sans-serif;
color: #FFFFFF;
background: transparent;
cursor: pointer;
}
.title_button_icon {width: 24px;}
First, we create the
.title
CSS rule to control the style of our title area.
Next we create the
.title_container
CSS rule to control the layout of our title container.
We include:
-
The
position: relative;
property to allow the title button to be positioned relative to the title container -
The
padding: 0 56px;
property to prevent the title heading and title button from overlapping
Then, we create the
.title_heading
CSS rule to control the style of our title heading.
Next we create the
.title_heading_link
CSS rule to control the style of our title heading link.
Then, we create the
.title_button
CSS rule to control the layout and style of our title button.
We include:
-
The
display: none;
property to hide the title button on devices that are not JavaScript-enabled -
The
position: absolute; right: 0; top: 0;
properties to position the title button in the top-right corner of the title container
Finally, we create the
.title_button_icon
CSS rule to control the style of our title button icon.
Navigation Structure and Style
The second item inside the header area is our navigation area.
The construction of the navigation area is similar to our Accordion Navigation Menu design. But we add:
- HTML and CSS to create the buttons used to open and close the subnavigation menus
Let's start with the HTML used to create the navigation area for our responsive subnavigation menu design:
HTML
<!-- Site Navigation -->
<nav class="nav-1">
<ul class="page">
<li class="nav-1_menu_item">
<a href="#home"
class="nav-1_menu_link">
Home</a></li>
<li class="nav-1_menu_item">
<a href="#about"
class="nav-1_menu_link">
About</a></li>
<li class="nav-1_menu_item">
<a href="#products"
onclick="subnavToggle(0)"
class="nav-1_menu_button">
Products
<span class="nav-1_menu_indicator">
<i class="nav-1_menu_icon fa fa-caret-down"></i></span></a>
<!-- Products Subnavigation -->
...
</li>
<li class="nav-1_menu_item">
<a href="#services"
onclick="subnavToggle(1)"
class="nav-1_menu_button">
Services
<span class="nav-1_menu_indicator">
<i class="nav-1_menu_icon fa fa-caret-down"></i></span></a>
<!-- Services Subnavigation -->
...
</li>
</ul>
</nav>
First, we create our navigation area using the
<nav>
element and assign it:
-
The
class="nav-1"
attribute to control the style of the navigation area
Inside the navigation area we create our navigation menu using the
<ul>
element and assign it:
-
The
class="page"
attribute to control the layout of the navigation menu
Inside the navigation menu we create our navigation menu items using the
<li>
element and assign each:
-
The
class="nav-1_menu_item"
attribute to control the layout and style of the navigation menu item
Inside the "Home" and "About" navigation menu items we use the
<a>
element to create a navigation menu link that directs visitors to the corresponding page when clicked.
We assign each:
-
The
href="..."
attribute to specify the destination of the navigation menu link -
The
class="nav-1_menu_link"
attribute to control the style of the navigation menu link
Inside the "Products" and "Services" navigation menu items, each of which has a subnavigation menu, we use the
<a>
element to create a navigation menu button that opens and closes the corresponding subnavigation menu.
We assign each:
-
The
href="..."
attribute to specify the link destination of the navigation menu button (for devices that are not JavaScript-enabled) -
The
class="nav-1_menu_button"
attribute to control the style of the navigation menu button
For the "Products" navigation menu button we also assign:
-
The
onclick="subnavToggle(0)"
attribute to execute the JavaScript function that opens and closes the "Products" menu when clicked. Note that the function includes an index number in parenthesis to identify which subnavigation menu node we wish to open. The JavaScript index starts at 0. Since the "Products" menu is the first node, its index number is 0.
For the "Services" navigation menu button we also assign:
-
The
onclick="subnavToggle(1)"
attribute to execute the JavaScript function that opens and closes the "Services" menu when clicked. Note that the function includes an index number in parenthesis to identify which subnavigation menu node we wish to open. The JavaScript index starts at 0. Since the "Services" menu is the second node, its index number is 1.
Inside the "Products" and "Services" navigation menu buttons we create our navigation menu indicators using the
<span>
element and assign each:
-
The
class="nav-1_menu_indicator"
attribute to control the style of the navigation menu indicator
And inside each navigation menu indicator we create our navigation menu icon using the
<i>
element and assign each:
-
The
class="nav-1_menu_icon fa fa-caret-down"
attribute to control the style of the navigation menu icon
Next the CSS:
CSS
/* Navigation */
.nav-1 {background: #000000;}
.nav-1.accordion {
overflow: hidden;
transition: height 0.25s;
}
.nav-1_menu_item {
display: block;
font: 16px / 1.5 sans-serif;
}
.nav-1_menu_link {
display: block;
padding: 16px;
text-decoration: none;
color: #FFFFFF;
}
.nav-1_menu_button {
display: block;
position: relative;
padding: 16px 48px;
text-decoration: none;
color: #FFFFFF;
}
.nav-1_menu_indicator {
display: none;
position: absolute;
right: 0;
top: 0;
padding: 16px;
}
.nav-1_menu_icon {width: 16px;}
@media (min-width: 480px) {
.nav-1_menu_item {display: inline-block;}
.nav-1_menu_button {
display: inline-block;
padding: 16px;
}
.nav-1_menu_indicator {
position: static;
padding: 0;
}
}
First, we create the
.nav-1
CSS rule to control the style of our navigation area.
To produce the accordion behavior, we create the
.accordion
CSS rule.
On small screens, our JavaScript function will add this CSS rule to the navigation area.
On medium and large screens, our JavaScript function will remove this CSS rule from the navigation area.
When added, this CSS rule applies:
-
The
overflow: hidden;
property to hide the content of the accordion navigation menu when it is closed -
The
transition: height 0.25s;
property to allow the height of the accordion navigation menu to change smoothly over a 0.25-second duration
Next we create the
.nav-1_menu_item
CSS rule to control the layout and style of our navigation menu items.
Note that the navigation menu items are displayed vertically (as blocks) on small screens and horizontally (as inline blocks) on medium and large screens.
Then, we create the
.nav-1_menu_link
CSS rule to control the style of our navigation menu links.
Next we create the
.nav-1_menu_button
CSS rule to control the layout and style of our navigation menu buttons.
We include:
-
The
position: relative;
property to allow each navigation menu indicator to be positioned relative to its respective navigation menu button -
The
padding: 16px 48px
property to prevent the navigation menu button text and navigation menu indicators from overlapping
Note that the navigation menu button padding changes to 16px on medium and large screens.
Then, we create the
.nav-1_menu_indicator
CSS rule to control the layout and style of our navigation menu indicators.
We include:
-
The
display: none;
property to hide the navigation menu indicators on devices that are not JavaScript-enabled -
The
position: absolute; right: 0; top: 0;
properties to position each navigation menu indicator in the top-right corner of its respective navigation menu button
Note that the subnavigation menu indicator position changes to static on medium and large screens.
Finally, we create the
.nav-1_menu_icon
CSS rule to control the style of our navigation menu icons.
Subnavigation Structure and Style
Inside the navigation area we create our subnavigation areas.
The construction of the subnavigation areas is similar to the construction of the navigation area in our Accordion Navigation Menu design. But we add:
- CSS to allow the dropdown behavior
Let's start with the HTML used to create the "Products" menu for our responsive subnavigation menu design:
HTML
<!-- Products Subnavigation -->
<div class="nav-2">
<ul class="page">
<li class="nav-2_menu_item">
<a href="#product-1"
class="nav-2_menu_link">
Product 1</a></li>
<li class="nav-2_menu_item">
<a href="#product-2"
class="nav-2_menu_link">
Product 2</a></li>
<li class="nav-2_menu_item">
<a href="#product-3"
class="nav-2_menu_link">
Product 3</a></li></ul>
</div>
Next the HTML used to create the "Services" menu for our responsive subnavigation menu design:
HTML
<!-- Services Subnavigation -->
<div class="nav-2">
<ul class="page">
<li class="nav-2_menu_item">
<a href="#service-1"
class="nav-2_menu_link">
Service 1</a></li>
<li class="nav-2_menu_item">
<a href="#service-2"
class="nav-2_menu_link">
Service 2</a></li>
<li class="nav-2_menu_item">
<a href="#service-3"
class="nav-2_menu_link">
Service 3</a></li></ul>
</div>
First, we create our subnavigation area using the
<div>
element and assign it:
-
The
class="nav-2"
attribute to control the style of the subnavigation area
Inside the subnavigation area we create our subnavigation menu using the
<ul>
element and assign it:
-
The
class="page"
attribute to control the layout of the subnavigation menu
Inside the subnavigation menu we create our subnavigation menu items using the
<li>
element and assign each:
-
The
class="nav-2_menu_item"
attribute to control the layout and style of the subnavigation menu item
And inside each subnavigation menu item we use the
<a>
element to create a subnavigation menu link that directs visitors to the corresponding page when clicked.
We assign each:
-
The
href="..."
attribute to specify the destination of the subnavigation menu link -
The
class="nav-2_menu_link"
attribute to control the style of the subnavigation menu link
And the CSS:
CSS
/* Subnavigation */
.nav-2 {
display: none;
font-size: 0;
text-align: center;
background: #808080;
}
.nav-2.accordion {
overflow: hidden;
transition: height 0.25s;
}
.nav-2.dropdown {
width: 100%;
position: absolute;
left: 0;
overflow: hidden;
transition: height 0.25s;
}
.nav-2_menu_item {
display: block;
font: 16px / 1.5 sans-serif;
}
.nav-2_menu_link {
display: block;
padding: 16px;
text-decoration: none;
color: #FFFFFF;
}
@media (min-width: 480px) {
.nav-2_menu_item {display: inline-block;}
}
First, we create the
.nav-2
CSS rule to control the style of our subnavigation areas.
We include:
-
The
display: none;
property to hide the subnavigation menu areas on devices that are not JavaScript-enabled -
The
font-size: 0;
property to prevent browsers from adding undesirable whitespace around and between the subnavigation menu items (font size is redefined later so that all text is rendered to the correct size)
To produce the accordion behavior, we create the
.accordion
CSS rule.
On small screens, our JavaScript function will add this CSS rule to the subnavigation areas.
On medium and large screens, our JavaScript function will remove this CSS rule from the subnavigation areas.
When added, this CSS rule applies:
-
The
overflow: hidden;
property to hide the content of the accordion subnavigation menus when they are closed -
The
transition: height 0.25s;
property to allow the height of the accordion subnavigation menus to change smoothly over a 0.25-second duration
To produce the dropdown behavior, we create the
.dropdown
CSS rule.
On small screens, our JavaScript function will remove this CSS rule from the subnavigation areas.
On medium and large screens, our JavaScript function will add this CSS rule to the subnavigation areas.
When added, this CSS rule applies:
-
The
width: 100%;
property to specify that the dropdown subnavigation menus expand the full width of the screen -
The
position: absolute; left: 0;
properties to position the dropdown subnavigation menus along the left of the screen -
The
overflow: hidden;
property to hide the content of the dropdown subnavigation menus when they are closed -
The
transition: height 0.25s;
property to allow the height of the dropdown subnavigation menus to change smoothly over a 0.25-second duration
Next we create the
.nav-2_menu_item
CSS rule to control the layout and style of our subnavigation menu items.
Note that the subnavigation menu items are displayed vertically (as blocks) on small screens and horizontally (as inline blocks) on medium and large screens.
Finally, we create the
.nav-2_menu_link
CSS rule to control the style of our subnavigation menu links.
Function
To complete our subnavigation menu design, we use JavaScript to add functionality to our layout. Keeping aligned with the principle of "progressive enhancement", the navigation menu remains fully functional for visitors without JavaScript-enabled devices. In this example, we assume that the pages contained in the subnavigation menus can be accessed through the pages contained in the navigation menu. So for visitors without JavaScript-enabled devices, the subnavigation menus are removed from our layout. But for visitors with JavaScript-enabled devices, the subnavigation menus are added to our layout to provide an improved user experience.
To produce this functionality, we show the subnavigation menus and initially close them by setting their height to 0. To allow visitors to toggle the subnavigation menus without sending them to a new page, we void the link destination of the "Products" and "Services" buttons. To alert visitors to the presence of the subnavigation menus, we show the navigation menu indicators. When the button is clicked to open one of the subnavigation menus, its height is set equal to the height of its content. When the button is clicked to close one of the subnavigation menus, its height is set back to 0.
On small screens, we add the accordion behavior and remove the dropdown behavior. Here the layout permits both subnavigation menus to be open at the same time.
On medium and large screens, we remove the accordion behavior and add the dropdown behavior. Here the layout permits only one subnavigation menu to be open at the same time. So when either subnavigation menu is opened, the other subnavigation menu is closed.
Let's take a look at a step-by-step breakdown of how we want the JavaScript to function:
When the page is loaded or resized:
-
If screen size is small:
- Add accordion behavior to navigation
- Collapse navigation
- Show navigation button
- Add accordion behavior to all instances of subnavigation
- Remove dropdown behavior from all instances of subnavigation
-
If screen size is medium or large:
- Remove accordion behavior from navigation
- Expand navigation
- Hide navigation button
- Remove accordion behavior from all instances of subnavigation
- Add dropdown behavior to all instances of subnavigation
- Show all instances of subnavigation
- Collapse all instances of subnavigation
- Void link destination of subnavigation button for all instances of subnavigation
- Show subnavigation indicator for all instances of subnavigation
When navigation is toggled:
-
If navigation is closed:
- Expand navigation
-
If navigation is open:
- Collapse navigation
- Collapse all instances of subnavigation
When subnavigation is toggled:
-
If screen size is small:
-
If selected instance of subnavigation is closed:
- Adjust height of navigation
- Expand selected instance of subnavigation
-
If selected instance of subnavigation is open:
- Adjust height of navigation
- Collapse selected instance of subnavigation
-
If selected instance of subnavigation is closed:
-
If screen size is medium or large:
-
If selected instance of subnavigation is closed:
- Collapse all instances of subnavigation
- Send all instances of subnavigation to back
- Expand selected instance of subnavigation
- Bring selected instance of subnavigation to front
-
If selected instance of subnavigation is open:
- Collapse selected instance of subnavigation
- Send selected instance of subnavigation to back
-
If selected instance of subnavigation is closed:
Now the JavaScript that makes it happen:
JavaScript
var screenSize = window.matchMedia("(max-width: 479px)");
// Navigation Variables
var nav = document.getElementsByClassName("nav-1");
var navButton = document.getElementsByClassName("title_button");
var subnav = document.getElementsByClassName("nav-2");
var subnavButton = document.getElementsByClassName("nav-1_menu_button");
var subnavIndicator = document.getElementsByClassName("nav-1_menu_indicator");
// Initial Setup of Navigation
function navInitial() {
// If Screen Size is Small
if (screenSize.matches) {
// Initial Setup of Navigation
nav[0].classList.add("accordion");
nav[0].style.height = "0";
navButton[0].style.display = "block";
// For All Instances of Subnavigation
for (i = 0; i < subnav.length; i++) {
// Initial Setup of Subnavigation
subnav[i].classList.add("accordion");
subnav[i].classList.remove("dropdown");
}
}
// If Screen Size is Medium or Large
else {
// Initial Setup of Navigation
nav[0].classList.remove("accordion");
nav[0].style.height = "auto";
navButton[0].style.display = "none";
// For All Instances of Subnavigation
for (i = 0; i < subnav.length; i++) {
// Initial Setup of Subnavigation
subnav[i].classList.remove("accordion");
subnav[i].classList.add("dropdown");
}
}
// For All Instances of Subnavigation
for (i = 0; i < subnav.length; i++) {
// Initial Setup of Subnavigation
subnav[i].style.display = "block";
subnav[i].style.height = "0";
subnavButton[i].href = "javascript:void(0);";
subnavIndicator[i].style.display = "inline-block";
}
}
// Toggle Navigation
function navToggle() {
// If Navigation is Closed
if (nav[0].style.height === "0px") {
// Open Navigation
nav[0].style.height = nav[0].scrollHeight + "px";
}
// If Navigation is Open
else {
// Close Navigation
nav[0].style.height = "0";
}
// For All Instances of Subnavigation
for (i = 0; i < subnav.length; i++) {
// Close Subnavigation
subnav[i].style.height = "0";
}
}
// Toggle Subnavigation
function subnavToggle(n) {
// If Screen Size is Small
if (screenSize.matches) {
// If Selected Instance of Subnavigation is Closed
if (subnav[n].style.height === "0px") {
// Adjust Navigation
nav[0].style.height = nav[0].scrollHeight + subnav[n].scrollHeight + "px";
// Open Selected Instance of Subnavigation
subnav[n].style.height = subnav[n].scrollHeight + "px";
}
// If Selected Instance of Subnavigation is Open
else {
// Adjust Navigation
nav[0].style.height = nav[0].scrollHeight - subnav[n].scrollHeight + "px";
// Close Selected Instance of Subnavigation
subnav[n].style.height = "0";
}
}
// If Screen Size is Medium or Large
else {
// If Selected Instance of Subnavigation is Closed
if (subnav[n].style.height === "0px") {
// For All Instances of Subnavigation
for (i = 0; i < subnav.length; i++) {
// Close Subnavigation
subnav[i].style.height = "0";
subnav[i].style.zIndex = "0";
}
// Open Selected Instance of Subnavigation
subnav[n].style.height = subnav[n].scrollHeight + "px";
subnav[n].style.zIndex = "1";
}
// If Selected Instance of Subnavigation is Open
else {
// Close Selected Instance of Subnavigation
subnav[n].style.height = "0";
subnav[n].style.zIndex = "0";
}
}
}
// When Page is Loaded
window.onload = navInitial;
// When Page is Resized
window.onresize = navInitial;
And there you have it! Responsive subnavigation menus.
The demonstration provided expands upon this code to show the header in a complete web page environment. It also includes extra features like tooltips, hover states, toggled icons, and button tabs.
To see it in action, open the demonstration at the beginning of this example in a new window. View the source code in your web browser to see how the page is constructed.
To customize the demonstration, first save a local copy of the document on your computer. Then, open the file in your text editor to add, remove, and modify code to create your own web design masterpiece.