Designing a navbar (or a toolbar) is easy for one screen size, but to make a truly responsive navbar, Flex Layout provides us with some neat tricks we can use!
If you are developing a web application, chances are you will need a navbar to display links to different sections of the site. That is all quite easy if your users are only on the desktop. But in today’s world, more of your users will be on the mobile or even tablets.
In this article, I will show you how to create a truly responsive navbar using Angular Material components and Flex Layout. Here is the final result:

Setting up the project
Let’s first quickly set up a new Angular project with Angular Material and Flex Layout by running these commands.
ng new responsive-toolbar
ng add @angular/material
npm install --save @angular/flex-layout
Next, let’s add our module dependencies to the app.module.ts:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
MatToolbarModule,
FlexLayoutModule,
MatMenuModule,
MatButtonModule,
MatIconModule,
MatDividerModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Setting up a new component
Once the project is set up, let’s start adding all the parts we need. First, let’s start by adding a new component to contain our responsive navbar.
ng generate component responsive-toolbar
We’ll be coming back to this in a bit. We want our menu items to be defined in code for re-use in both the buttons and drop-down menu. So let’s also add a model for the menu item.
It’s strictly not needed, but with typescript it is always better to specify types – it gives a bit of structure to new developers and makes the development process easier by code hints in templates.
ng generate interface menu-item
export interface MenuItem {
label: string;
icon: string;
}
A basic responsive navbar
Let’s now add the menu items to our component. Here’s the responsive toolbar component:
@Component({
selector: 'app-responsive-toolbar',
templateUrl: './responsive-toolbar.component.html',
styleUrls: ['./responsive-toolbar.component.scss']
})
export class ResponsiveToolbarComponent implements OnInit {
menuItems: MenuItem[] = [
{
label: 'Sign Up',
icon: 'login'
},
{
label: 'About',
icon: 'help'
},
{
label: 'Pricing',
icon: 'attach_money'
},
{
label: 'Docs',
icon: 'notes'
},
{
label: 'Showcase',
icon: 'slideshow'
},
{
label: 'Blog',
icon: 'rss_feed'
},
];
constructor() { }
ngOnInit(): void {
}
}
We’re just declaring the menu items array here. Let’s look at the template where the actual magic happens.
<mat-toolbar fxLayout="row" color="primary">
<span fxFlex>Responsive Toolbar Demo</span>
<button mat-button *ngFor="let item of menuItems" fxHide.xs>
<mat-icon class="mr">{{item.icon}}</mat-icon>
{{item.label}}
</button>
<button mat-icon-button [matMenuTriggerFor]="dropMenu" fxHide fxShow.xs>
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #dropMenu="matMenu">
<ng-container *ngFor="let item of menuItems">
<button mat-menu-item>
<mat-icon class="mr">{{item.icon}}</mat-icon>
{{item.label}}
</button>
<mat-divider></mat-divider>
</ng-container>
</mat-menu>
</mat-toolbar>
Let’s go through what we’ve done in the template.
- We have added a material toolbar component which contains everything
- We’re using Flex Layout’s
fxLayout
directive to specify that everything in the container will be laid out in a row - We’ve an
*ngFor
directive which we’re using to create a button with icon for each menu item. - We’ve a “more” button icon at the end of the row, which triggers a material dropdown menu containing our items.
All this is fine and well. But where is the responsive code? If you look closely, we also have fxHide
and fxShow
in some places. Basically, Flex Layout provides us with these directives and their breakpoint suffixes (such as xs, sm etc.) so that we can hide or show different elements at different screen sizes.
The behavior that we want is that the menu buttons should show when on desktop, but on mobile sizes, should all compress into a ‘more’ button and a dropdown menu.
For the top buttons, the default is they’ll be shown (we don’t need to specify), so we use fxHide.xs
to hide them when on mobile. Conversely, the default for the dropdown menu would be hidden, so we use fxHide
. But then we use fxShow.xs
to show the icon button at mobile sizes.
Here is how it looks!

We want more control
This is all looking good. However, as you can see in the animation above, our buttons compress into each other when we begin approaching the mobile size. It would be nice if we can have more control over which buttons to show on this intermediary size (e.g. tablet).
For that to happen though, we need to add a bit more code. This will allow us to specify which menu item to show in the buttons menu or dropdown menu and on which screen sizes.
Let’s modify our menu item interface to accommodate this flexibility.
export interface MenuItem {
label: string;
icon: string;
showOnMobile: boolean;
showOnTablet: boolean;
showOnDesktop: boolean;
}
We added three boolean types to specify for each item, where it should show and should not show.
Next, let’s update out menu items array.
menuItems: MenuItem[] = [
{
label: 'Sign Up',
icon: 'login',
showOnMobile: true,
showOnTablet: true,
showOnDesktop: true
},
{
label: 'About',
icon: 'help',
showOnMobile: false,
showOnTablet: true,
showOnDesktop: true
},
{
label: 'Pricing',
icon: 'attach_money',
showOnMobile: false,
showOnTablet: false,
showOnDesktop: true
},
{
label: 'Docs',
icon: 'notes',
showOnMobile: false,
showOnTablet: true,
showOnDesktop: true
},
{
label: 'Showcase',
icon: 'slideshow',
showOnMobile: false,
showOnTablet: false,
showOnDesktop: true
},
{
label: 'Blog',
icon: 'rss_feed',
showOnMobile: false,
showOnTablet: false,
showOnDesktop: false
},
];
As you can see, we’re specifying the “Sign-up” menu item to appear at the top on all breakpoints. In other words, it is getting the highest priority. These items will be useful for most used features in any app. Having prominent links to such features helps our users and ultimately the product in the end!
On the other hand, notice how the “Blog” section is never shown at the top. This is just an example, but you can have unimportant sections in your apps, which you need for completeness, but users don’t really need that much. So this section will just appear in the menu as an additional option when users want (or go looking for it).
Making the navbar truly responsive
The only thing that’s left now is to actually add handling for this data to our templates. Here is how the template looks now.
<mat-toolbar fxLayout="row" color="primary">
<span fxFlex>Responsive Toolbar Demo</span>
<button mat-button *ngFor="let item of menuItems"
[fxShow]="item.showOnDesktop"
[fxShow.xs]="item.showOnMobile"
[fxShow.sm]="item.showOnTablet">
<mat-icon class="mr">{{item.icon}}</mat-icon>
{{item.label}}
</button>
<ng-container>
<button mat-icon-button [matMenuTriggerFor]="dropMenu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #dropMenu="matMenu">
<ng-container *ngFor="let item of menuItems">
<div [fxShow]="!item.showOnDesktop"
[fxShow.sm]="!item.showOnTablet"
[fxShow.xs]="!item.showOnMobile">
<button mat-menu-item>
<mat-icon class="mr">{{item.icon}}</mat-icon>
{{item.label}}
</button>
<mat-divider></mat-divider>
</div>
</ng-container>
</mat-menu>
</ng-container>
</mat-toolbar>
The only difference in this and the previous version is in how we’re now using the new properties we defined for each item and binding them with Flex Layout’s directives.
For the top buttons, we’re binding each item’s fxShow
directive to the corresponding breakpoint.
As an example, fxShow.xs
binds to item.showOnMobile
– in other words, we’re telling the button for that item to only show on top on mobile, when it has showOnMobile
to true
. The logic is similar for desktop and tablet.
For the dropdown menu items, notice we’re not hiding or showing the “more” icon anymore, but instead adding more fine control over individual menu items.
This is the power of Flex Layout, where you can add a directive to virtually anything in the DOM. Check out another article on how to build a responsive card grid using flex layout here!
For the dropdown menu items though, we use a reverse logic.
As an example, fxShow.xs
binds to !item.showOnMobile
– in other words, we’re telling the button for that item to only show in the dropdown on mobile, when it has showOnMobile
to false
. This is when the button would be hidden on top.
The result of these changes will be the menu items moving in and out of the top buttons and the dropdown menu as the screen size changes. When they are hidden on the top, they get added to the dropdown and reverse!
And we’re done! Here is the result – a truly responsive, flexible navbar (or toolbar) ready for you to use in your projects.

Next steps
As you might have noticed, I didn’t add any real navigation functionality to the menu items. To do that, you could add a route property and use it navigate to the same for each item. And if you want to build upon this, you could also add nesting to the menu according to your needs.
The sky is the limit in this case!
Thanks for reading! If you have any comments, or want to share a better way to achieve this, fire up a comment below.
The final code for this tutorial can be found here.
Bye! ?
Muy buena guía amigo, me sirvió bastante. Podría hacer una con un menú desplegable? es decir, que el inicio despliegue otros ítem, y así los demás.
Translated:
Very good guide friend, it helped me a lot. Could you make one with a drop down menu? that is, that the beginning displays other items, and so on the others.
Hey Jose!
Thanks for your comment and it was great to see you found this useful. Could you please specify a bit further about what you’d like me to write about? Do you mean a responsive drop down menu?
Nice 1 – best responsive navbar setup in terms of boilerplate-lessness that i’ve seen so far! Would love to see an side-nav example as well!
Hey Wolfgang!
Thanks for your comment and glad you liked this.
About a side-nav, it usually ends up folded in mobile view and can be opened up with a hamburger icon. For a desktop view we can keep it visible. Are you looking for an example for this?
If so, I’d be happy to help out 🙂
Hi Zoaib,
I’m trying to add some real navigation functionality to the menu items to your “responsive-toolbar” tuorial.
You mentioned above to add route property and use it to navigate to the same for each item.
But I’m needing a bit more info if possible.
I’ve:
1. Imported RouterModule and Routes into my routing module.
2. Define your routes in your Routes array.
3. Not sure how to add Add your routes to your application when using button array
Should I try to utilize routerLink?
I’m having trouble finding the onClick or should the routing do the job when using the ‘menuItems: MenuItem[]’ array inside export class ResponsiveToolbarComponent?
Thanks for any assistance.
Cheers,
Wayne
Hey Wayne!
Thanks for the comment.
So you’ll need to use the following way to add routing to the app and link with the responsive menu:
1) Include RouterModule in your app and define your routes array. – this will be where the route will be loaded
2) Add the ‘route’ property to the menu item and add it to the menu array for each item.
3) In the app.component.html below the toolbar, you’ll need to add
4) Lastly, you need to add [routerLink]=”item.route” to both the floating and toolbar buttons
That should be enough. Hope this helps!
Regards,
Zoaib 🙂
Thanks for the informative, excellent and quick response Zoaib, it is much appreciated.
I understand all but point 4) “4) Lastly, you need to add [routerLink]=”item.route” to both the floating and toolbar buttons”
Where in the code do I add the router link? I’assuming in either in responsive-toolbar.component.html or responsive-toolbar.component.ts… so I can for example jump to my Client or About component pages.
In my example, it should be added to the HTML button tags, both in the toolbar and also inside the mat menu. This is in the app.component.html file!
I am a little confused about step 3 here
Ok thanks so much Zoaib.. and I look forward to checking out your other tutorials!
Sure, you’re welcome 🙂
these is all good but how to add navigation for particular button
To add navigation, just keep a route property with the others in the JSON.
Then in the template, use [routerLink]=”item.route” to link it all up.
Regards
Excellent stuff, exactly what I was looking for. Thaks for sharing this simple setup that can be easily extended, uses flex-layout and does not use any custom css.
this is great, however, I am wondering how i am supposed to be routing with the buttons as a for loop with the array
Hey Amy!
Thanks for the comment. You just need to add the
item.route
in the routerLink for each button and ensure therouter-outlet
is present in the template + the routes are set up in the app module or separate routing module.