Adding a Mobile Burger Menu to the App

The mobile nav finally got its own proper button

Today’s build was small on paper but felt like a real product moment: I added a mobile burger menu to the app. The desktop nav already worked fine, but on a phone it was doing that awkward thing where links either squeezed into a tiny row or wrapped into a second line and made the header look broken.

I kept ignoring it because the app still functioned. Classic builder trap. But every time I opened it on my phone, the first impression felt unfinished. So this session was about cleaning that up, making the header behave properly on smaller screens, and setting up the navigation in a way that will not fight me later when I add more pages.

The goal was simple: desktop users see the normal nav links, mobile users see a burger button, and tapping that button opens a menu with the same links stacked vertically.

The starting point

The app already had a basic header component. Nothing fancy. Logo on the left, nav links on the right, a bit of spacing, and active link styling. It worked well enough on a laptop.

On mobile, not so much.

The header had been built during an earlier sprint when I was focused on getting the main app flow working. I had left responsiveness for later, which is usually fine when you are moving fast, but eventually “later” shows up and asks for payment.

The first thing I did was open the app in responsive mode and drag the viewport down from desktop width to phone width. Around the tablet-to-phone breakpoint, the layout started to feel cramped. At smaller widths, the links became too close together and the header height started growing.

That was the sign. Time for a burger menu.

The behavior I wanted before touching code

Before changing the component, I wrote down the actual behavior I wanted. This helps me avoid building three versions of the same thing because I keep changing my mind mid-file.

  • On desktop, show the logo and full navigation links.

  • On mobile, hide the full nav links.

  • Show a burger icon button on mobile.

  • When the button is tapped, open a vertical menu below the header.

  • When a link is tapped, close the mobile menu.

  • When the menu is open, change the icon so the state is obvious.

  • Keep the markup simple enough that future me can edit it without sighing.

I did not want a full-screen animated drawer yet. That might come later, but for this version it would have been too much. The app just needed a clean mobile nav that worked.

Adding the menu state

The first real change was adding a small state value to the header component. I called it something plain like isMenuOpen. No magic naming. It stores whether the mobile menu is visible or not.

The burger button toggles that value. Tap once, the menu opens. Tap again, it closes.

This is one of those tiny interactions that makes an app feel alive. The code is not complex, but it adds a layer of polish users instantly understand. They do not care how it works. They just expect it to work.

I also made sure the menu closes when someone taps a link. That part is easy to forget. If you leave it out, users tap a page, the route changes, and the menu stays hanging open on the new screen. It feels messy.

Separating desktop and mobile nav

Next, I split the navigation visually using responsive classes. The desktop nav stays visible on larger screens. The mobile button only appears on smaller screens.

The trick here was not to create two completely separate navigation systems. I still wanted one source of truth for the links. So I kept the nav items in one small list and rendered them in both places: once for the desktop row, once for the mobile stack.

That keeps the app easier to maintain. If I add a new page later, I only add it to the nav array once. The desktop and mobile menus both pick it up.

This was one of the better choices in the session. It took a few extra minutes, but it prevents that annoying future bug where the desktop menu has five links and the mobile menu only has four because I forgot to update both.

The first version looked fine, then immediately broke

The first pass worked in the browser, but the spacing was off. The mobile menu opened, but it felt glued to the header. The links were too close together, and the tap targets were smaller than I liked.

That is the thing with navigation. It can technically work and still feel bad.

I added more vertical padding to each link and gave the menu container a little breathing room. I also made the menu width match the header area so it felt connected instead of floating randomly under it.

Then I noticed another issue. The open menu was pushing content down, which was expected, but the transition felt sudden. I tested a quick animation, but it started to make the component feel heavier than needed. I pulled it back. For now, instant open and close is fine. Fast beats cute here.

The win was not building the flashiest menu. The win was making the app feel finished on a phone without adding extra complexity.

Making the button feel like a real control

The burger icon itself needed a little care. I did not want it to be just a random icon inside a div. It needed to be a real button so tapping, accessibility, and browser behavior all made sense.

I used a button element, added an accessible label, and tied the visual icon to the menu state. When the menu is closed, it shows the burger icon. When the menu is open, it changes to a close icon.

That tiny icon swap matters. Without it, the user has to guess whether tapping the burger again will close the menu. With the close icon, the action is obvious.

I also checked the touch area. On mobile, tiny buttons are hostile. The button got enough padding so it is easy to tap with a thumb, even if someone is using the app one-handed while half-paying attention.

The responsive breakpoint decision

I had to choose where the desktop nav disappears and the burger menu takes over. This is one of those decisions that can turn into a rabbit hole if you let it.

I started with the standard medium breakpoint because it matched the rest of the app’s layout. Then I tested it with the current nav labels. It looked good. The nav had enough room on tablet and desktop, and the burger menu appeared before the links started feeling cramped.

The lesson here was simple: use the design system’s existing breakpoints unless the interface gives you a clear reason not to. Random one-off breakpoints make styling harder to reason about later.

Screen sizeNavigation behaviorReason
DesktopFull nav links visiblePlenty of horizontal space
TabletFull nav stays visible if it fits cleanlyAvoid hiding links too early
PhoneBurger button with stacked menuBetter tap targets and cleaner header

Closing the menu after navigation

This was a small but satisfying fix. Each mobile menu link now calls the close function when clicked.

At first, I only wired up the button toggle and forgot about link clicks. The menu opened perfectly, but after choosing a route, it stayed open. That made the app feel like it had not fully reacted to the user’s choice.

The fix was easy. Add the same close action to each mobile link. Once tapped, the link does its normal navigation job and the menu state resets to closed.

That kind of detail is easy to skip while vibe coding because the main feature already seems done. But it is also the kind of detail people feel immediately when they use the app.

Keeping the menu data clean

I took a quick detour to clean up the nav link structure. Instead of writing each link by hand in two spots, I made a simple array of nav items. Each item has a label and a path.

Then the desktop nav maps through that array. The mobile nav does the same. Same data, different layout.

This is not a big architecture move. It is just tidy. But tidy compounds. When the app grows, these small choices save time and reduce silly mistakes.

  • One nav list feeds both desktop and mobile menus.

  • Labels stay consistent across screen sizes.

  • New pages can be added in one place.

  • The header component stays easier to scan.

Testing it like a normal user

After the code looked right, I stopped looking at the component and started using the app like a person. I opened it on a narrow viewport, tapped around, changed pages, opened and closed the menu a bunch of times, and resized the browser back and forth.

A few things I checked:

  • The menu button only appears on mobile.

  • The desktop nav returns cleanly when the screen gets wider.

  • The mobile menu does not stay open after tapping a link.

  • The header height does not jump in a weird way.

  • The icon state matches the menu state.

  • The links are comfortable to tap.

I also tested one annoying edge case: open the mobile menu, then resize to desktop. If the open state stays true behind the scenes, it can sometimes create strange behavior when resizing back down. In this version, the layout still behaved fine, but I made a note to possibly close the menu automatically on breakpoint changes later if it ever causes trouble.

What I almost added but skipped

I had a few tempting ideas while building this. Slide-down animation. Blurred backdrop. Full-screen drawer. Maybe even locking body scroll when the menu is open.

I skipped all of it for now.

The app does not need a dramatic navigation experience yet. It needs clear access to pages on a phone. That is the feature. The rest can wait until the product asks for it.

This is a pattern I keep learning the hard way. The best version one is usually the smallest version that removes the pain. The pain here was cramped mobile navigation. A simple burger menu removes it.

The final shape of the feature

By the end of the session, the header felt much better. On desktop, nothing changed in a noticeable way. That is good. Existing behavior stayed stable. On mobile, the header now has a clear burger button, the menu opens below it, and the links are easy to tap.

The feature now has a clean little flow:

  • User lands on the app from a phone.

  • Header shows logo and burger button.

  • User taps the burger button.

  • Mobile menu opens with stacked nav links.

  • User taps a link.

  • The app navigates and the menu closes.

Simple. Predictable. Much better than a cramped row of tiny links.

What this taught me

This was one of those builds where the feature is common, but the value comes from doing it cleanly. A mobile burger menu is not new or flashy. Still, adding it made the app feel more complete because navigation is one of the first things people touch.

The biggest reminder was to build the behavior first, then dress it up. State, toggle, render conditionally, close on click. Once that flow worked, styling became much easier because I was not guessing anymore.

I also liked the decision to keep the nav items in one shared list. That little cleanup turned a visual fix into a better component. Not a rewrite. Not a big refactor. Just enough structure to keep future edits painless.

The next pass might include keyboard focus styling, a smoother open state, and maybe closing the menu when tapping outside it. For now, the app has a working mobile burger menu, and the phone experience no longer looks like an afterthought.

That is a good build session.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top