Dynamic responsive navigation menus and coding them in Angular

Joe Alongi
8 min readOct 13, 2024

--

People are familiar with menus, lists of items, and choices that are available for a topic, often organized by categories. Websites, applications, and software utilize this cognitive familiarity to provide an experience of choices across a digital path that is often referred to as routing.

When coding applications it is important to consider the methodology that is applied as the result of the menu. From single-page applications that reload a content frame to multi-page implementations that narrow the view of content, these choices impact the experience of the user.

Menus are portals to your content, the funnel to your sales, and the avenue in which users travel to information, how this is implemented is important.

Exploring the development of Angular web menus will reveal considerations that allow for scaling of the application to meet the demands of enterprise software.

Structuring the menu in Angular

As a fundamental concept, like sketching out a draft, creating an initial layout skeleton for the menu is a great step to get content into the template. Coding this step in HTML as a static variant will illuminate the requirements of the menu and enable further enhancement when moving to a dynamic format.

<header id="header">
<div id="navbar">
<nav id="menu">
<ul>
<li>
<a href="/">Menu Item One</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Two</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Three</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Four</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Five</a>
</li>
</ul>
</nav>
</div>
</header>

When implementing the static menu it is important to incorporate the best practices for HTML markup so that the menu is structured within an accessible space.

As a good practice, links can be more efficiently structured as an unordered list with list item elements that render and style more efficiently than div items.

Adding styles to the menu in Angular

As the static method structures the interactive elements of the menu, styling applies fluidity to the layout in a way that animates the experience. Coding this step in CSS and adding classes and ids in HTML configures the menu to function outside of its native behavior.

.flex-row {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
flex-flow: column nowrap;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
height: auto;
width: 100%;
padding: 0;
margin: 0;
gap: 0;
}

.flex-row-item {
flex: 1;
order: 0;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
align-self: flex-start;
height: auto;
width: 100%;
padding: 0;
margin: 0;
}

#header {
position: relative;
z-index: 1000;
height: auto;
width: 100%;
}

#navbar {
flex-direction: row;
flex-wrap: nowrap;
flex-flow: row nowrap;
height: auto;
width: 100%;
padding: 9px;
margin: 0 auto;
}

#navbar .menu {
display: none;
visibility: hidden;
}

#navbar .menu ul li a {
display: block;
color: #0d160b;
padding: 9px;
border-bottom-width: thick;
border-bottom-style: solid;
border-bottom-color: transparent;
}

#navbar .menu ul li a:hover,
#navbar .menu ul li a:active {
border-bottom-width: thick;
border-bottom-style: solid;
border-bottom-color: #002673;
}

Developing a global class for overwriting the natural hierarchy of the list which naturally appears on the page as a vertical structure with a bulleted list allows for a fluid menu. Through the flexbox layout, the top-to-bottom list can be altered based on the screen orientation. Starting with the smallest device in consideration first is the best process for building up to a larger scale display.

Incorporating additional hierarchical classes for controlling the look and feel of the menu and the container that holds it. will allow for the encompassing styling that sets up this menu.

<header id="header">
<div id="navbar" class="flex-row">
<nav id="menu" class="flex-row-item">
<ul class="flex-row">
<li class="flex-row-item">
<a href="/">Menu Item One</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Two</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Three</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Four</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Five</a>
</li>
</ul>
</nav>
</div>
</header>

Together the HTML and CSS join to create the structure of the menu which will render an effective navigation bar within the Angular DOM as a template for the next stages of development.

Responsively enabling the menu in Angular

Now that the structure for the menu and styling with classes and ids are in place, the menu can become adaptive using media queries. The initial styling was focused on the mobile implementation of the navbar and this iteration will cover all use cases, from mobile up to desktop.

@media screen and (min-width: 768px) {
.flex-row {
flex-direction: row;
flex-wrap: nowrap;
flex-flow: row nowrap;
}

#navbar {
padding: 9px 18px;
}
}

@media screen and (min-width: 1280px) {
#navbar {
padding: 9px 27px;
}

#navbar .mobile-menu-icon,
#navbar-mobile {
display: none;
visibility: hidden;
}

#navbar .menu {
display: block;
align-self: center;
visibility: visible;
}

#navbar .menu {
height: auto;
width: auto;
padding: 0;
margin: 0;
align-self: center;
}

#navbar .menu li {
margin: 0 9px 0 0;
}
}

@media screen and (min-width: 1400px) {
#navbar {
padding: 9px 9vw;
}
}

In this series of CSS updates, enabling the row variant of the flexbox layout allows the menu to flow in a horizontal pattern that meets the expected desktop standard. Coding in this step with CSS and HTML to add additional elements into the navbar, builds onto the mobile visibility and enables accessible navigation on any device.

<header id="header">
<div id="navbar" class="flex-row">
<a
class="logo flex-row-item"
href="/"
target="_self"
rel="noreferrer noopener"
aria-label="Buffalo Compute Link"
type="link"
><img
src="/assets/BuffaloComputeAppAlt.png"
loading="eager"
height="30"
width="30"
/></a>
<button
class="mobile-menu-icon flex-row-item"
type="button"
(click)="toggleMobileMenu()"
clickable
>
<img
src="/assets/mobile-menu-icon.svg"
loading="eager"
height="30"
width="30"
/>
</button>

<nav class="menu flex-row-item">
<ul class="flex-row">
<li class="flex-row-item">
<a href="/">Menu Item One</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Two</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Three</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Four</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Five</a>
</li>
</ul>
</nav>
</div>
</header>

@if (navbarMobileVisible === true) {
<nav id="navbar-mobile" aria-label="Buffalo Compute Navbar Mobile">
<ul class="flex-row">
<li class="flex-row-item">
<a href="/">Menu Item One</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Two</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Three</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Four</a>
</li>
<li class="flex-row-item">
<a href="/">Menu Item Five</a>
</li>
</ul>
</nav>
}

As an element of the navbar layout, coding again in HTML and using Angular @ if { } for conditioning to introduce a logo and menu button. An additional mobile menu creates distinct experiences for device and desktop versions. As an additional step, the mobile menu requires a handler for the click event listener stored in the component file.

import { Component } from '@angular/core';

@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrl: './navbar.component.css',
standalone: true,
})
export class NavbarComponent {
navbarMobileVisible = false;

toggleMobileMenu() {
this.navbarMobileVisible = !this.navbarMobileVisible;
}

}

Coding a variable into the component with the boolean data type allows for setting and handling of the menu through the click event with additional considerations to the CSS.

Dynamically rendering the menu in Angular

As the elements are sorted into an efficient mental model as a tree of navigation to the application’s destinations, it is now important to reduce the complexity of the DOM render. Dynamically rendering the menu based on the display’s scale, user’s active choices, and storing that data in a more uniform format enables reusability.

<header id="header">
<div id="navbar" class="flex-row">
<a
class="logo flex-row-item"
href="/"
target="_self"
rel="noreferrer noopener"
aria-label="Buffalo Compute Link"
type="link"
><img
src="/assets/BuffaloComputeAppAlt.png"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Logo"
/></a>
<button
class="mobile-menu-icon flex-row-item"
aria-label="Buffalo Compute Mobile Menu"
type="button"
(click)="toggleMobileMenu()"
clickable
>
<img
src="/assets/mobile-menu-icon.svg"
loading="eager"
height="30"
width="30"
alt="Buffalo Compute Mobile Menu Icon"
/>
</button>

<nav class="menu flex-row-item">
<ul class="flex-row">
@for (link of links; track $index) {
<li class="flex-row-item">
<a
[href]="link.href"
target="_self"
rel="noreferrer noopener"
type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>
</div>
</header>

@if (navbarMobileVisible === true) {
<nav id="navbar-mobile" aria-label="Buffalo Compute Navbar Mobile">
<ul class="flex-column">
@for (link of links; track $index) {
<li class="flex-row-item">
<a [href]="link.href" target="_self" rel="noreferrer noopener" type="link"
>{{ link.text }}</a
>
</li>
}
</ul>
</nav>
}

Applying the menu items conditionally with @ for () {} so that the list stored in the component is iterated dynamically instead of rendered statically, allowing all navigation menus to draw from the same data source. At this stage, it is also valuable to set the target attribute, rel attribute, and aria type to declare the specific use and screenreading functionality of the links.

import { Component } from '@angular/core';

@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrl: './navbar.component.css',
standalone: true,
})
export class NavbarComponent {
navbarMobileVisible = false;

toggleMobileMenu() {
this.navbarMobileVisible = !this.navbarMobileVisible;
}

links = [
{ text: 'Home', href: '/' },
{ text: 'About', href: '/about' },
{ text: 'Articles', href: '/articles' },
{ text: 'Blueprints', href: '/blueprints' },
{ text: 'Tools', href: '/tools' },
];
}

Coding the dynamic rendering based on the variable stored in the component requires composing an array of objects that will be iterated across through the component’s template.

Calling the menu component in Angular

Once the complete set of component configurations is in place, the component is then called in a top-level page that calls upon the component when the application loads.

<main id="app">
<app-navbar />
</main>

As a complete set of styling, dynamic rendering, and component structuring, the application now has a complete navigation bar that is accessible across all resolutions. Experiences based around the navigation bar can be extended to increase the value, from drop-downs to pop-overs, the information here is the start of the user’s journey.

Join in on the adventure at heyitsjoealongi.com and on X, Instagram, GitHub, and LinkedIn. For more articles like this subscribe on Substack.

--

--

No responses yet