Skip to main content
RapidDev - Software Development Agency
weweb-tutorial

WeWeb Navigation: Custom Menus, Headers, and Footers

WeWeb includes built-in Top Navigation Bar, Side Menu, and Bottom Navigation components. Shared headers and footers across pages are configured as multi-page sections. You can add active-state styling, role-based menu item visibility, a mobile hamburger menu, and dynamic menus driven by a data collection — all without custom code for most use cases.

What you'll learn

  • How to add and configure WeWeb's built-in navigation components (Top Nav, Side Menu, Bottom Nav)
  • How to create shared headers and footers that appear across multiple pages using multi-page sections
  • How to add active-state styling to navigation links and a working mobile hamburger menu
  • How to show or hide menu items based on user role using conditional visibility
  • How to build a dynamic navigation menu driven by a data collection
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner12 min read25–40 minWeWeb Free plan and aboveMarch 2026RapidDev Engineering Team
TL;DR

WeWeb includes built-in Top Navigation Bar, Side Menu, and Bottom Navigation components. Shared headers and footers across pages are configured as multi-page sections. You can add active-state styling, role-based menu item visibility, a mobile hamburger menu, and dynamic menus driven by a data collection — all without custom code for most use cases.

Building Navigation Menus and Shared Headers in WeWeb

Navigation is the backbone of any multi-page app. WeWeb provides purpose-built navigation components — Top Navigation Bar, Side Menu, and Bottom Navigation — that handle the structural and responsive work for you. Beyond the built-in components, WeWeb's multi-page sections feature lets you define a header or footer once and display it across any combination of pages. This tutorial walks through setting up each navigation pattern, adding active link states, building a mobile hamburger toggle, restricting menu items to specific user roles, and creating a menu whose items are populated dynamically from a data collection.

Prerequisites

  • A WeWeb project with at least two pages
  • Basic familiarity with the WeWeb editor canvas, left panel, and Styling panel
  • Optional: a Supabase or other auth plugin installed if you want role-based menu items

Step-by-step guide

1

Add a Top Navigation Bar component

In the left panel, click the Add element icon (+) → scroll to Navigation → drag Top Navigation Bar onto your canvas. The component renders immediately with default placeholder links. Select the component to see its Settings panel on the right. The Settings panel exposes: Logo (image or text), Navigation links (list of label + page/URL pairs), CTA button (optional right-side action), and Mobile breakpoint threshold (the pixel width at which the hamburger menu replaces the full nav). Click any navigation link in the Settings panel to edit its label and destination. Click the + icon to add new links. Links can point to WeWeb pages (select from dropdown) or external URLs. The Top Navigation Bar automatically collapses to a hamburger menu at Mobile breakpoint — no workflow needed for this basic behavior. Style the nav by selecting it and using the Styling panel: background color, padding, border-bottom, sticky positioning (set position to 'sticky', top to 0, z-index to 100).

Expected result: A functional navigation bar appears at the top of your page with clickable links that navigate between pages, and a hamburger menu appears on Mobile.

2

Create a shared header with multi-page sections

The Top Navigation Bar component placed on one page only appears on that page. To share a header across multiple pages, use WeWeb's multi-page sections feature. First, design your header section on the page where you want to start. This can be the Top Navigation Bar component inside a Section, or any custom header layout you build. Once your header looks correct, select the Section that wraps the header content (in the left Navigator panel, find the topmost Section). Right-click the Section → 'Turn into linked section' (or from the top right context menu, look for 'Linked section'). A dialog appears asking which pages should display this section. Check all the pages you want. The section now appears at the top of every selected page, and any change you make to it on one page updates it everywhere. To add or remove pages from the shared section later: select the linked section → Settings panel → 'Manage pages'. Footers work identically — create a section at the bottom, link it across pages.

Expected result: Your header section appears on all selected pages simultaneously. Changing it on one page updates all linked pages.

3

Add active-state styling to navigation links

Active link highlighting — where the current page's nav item visually differs from others — requires a binding formula. For each navigation link element, go to Styling panel → create a CSS class (e.g., 'nav-link'). Then add a subclass for the active state. The simplest approach uses a binding: select the navigation link → Styling panel → bind the color or border-bottom property → use the formula: `if(wwContext.pageId === 'YOUR_PAGE_ID', '#active-color', '#default-color')`. You can find each page's ID in the page URL in the WeWeb editor. A cleaner approach: bind a CSS class to the nav item using the formula. Create two classes — 'nav-link' and 'nav-link-active'. Then in the Settings panel → bind the element's class list to: `['nav-link', wwContext.pageId === 'YOUR_PAGE_ID' ? 'nav-link-active' : '']`. Repeat for each nav link with its corresponding page ID.

typescript
1/* Injection point: Styling panel → CSS Classes → nav-link-active class definition */
2
3/* Base nav link style */
4.nav-link {
5 color: #374151;
6 font-weight: 500;
7 padding: 8px 12px;
8 border-radius: 6px;
9 text-decoration: none;
10 transition: background-color 0.15s ease;
11}
12
13/* Active page indicator */
14.nav-link-active {
15 color: #6366f1;
16 background-color: #eff0ff;
17 font-weight: 600;
18}
19
20/* Hover state on non-active links */
21.nav-link:not(.nav-link-active):hover {
22 background-color: #f3f4f6;
23}

Expected result: The current page's navigation link is visually highlighted while other links remain in their default style.

4

Build a mobile hamburger menu with workflow

If you are using the built-in Top Navigation Bar, the hamburger menu is already included. For a custom navigation layout: first, create two elements — a desktop navigation container (visible on Desktop and Tablet, hidden on Mobile) and a mobile hamburger icon element (hidden on Desktop and Tablet, visible on Mobile). At Mobile breakpoint in the Styling panel, set the desktop nav's display to 'none' and the hamburger icon's display to 'flex'. Second, create a mobile menu panel — a full-width container positioned below the nav with your mobile links. Set this container's display to 'none' by default. Third, create a Boolean variable: Data panel → Variables → New → Boolean → name it 'mobileMenuOpen' → default value false. Fourth, bind the mobile menu container's display property to: `if(mobileMenuOpen, 'flex', 'none')`. Fifth, add a workflow to the hamburger icon: Workflows → On click → Action: Change variable value → mobileMenuOpen → Toggle (or set to true). Add a second workflow to each mobile link: On click → Change variable value → mobileMenuOpen → set to false (to close the menu after navigation).

Expected result: Tapping the hamburger icon toggles a mobile menu open and closed. Tapping a link closes the menu.

5

Show and hide menu items by user role

Frontend role-based menu visibility is a UX feature, not a security measure. A user with the wrong role can still access a page if they know the URL — true access control requires page-level access restrictions (Page settings → Access control, Scale plan required) AND backend RLS policies. With that caveat stated: to hide menu items for specific roles, use Conditional Rendering. Select the nav link element you want to restrict → Settings panel → Conditional Rendering → click the plug icon → write a formula referencing the current user's roles. With Supabase Auth: the formula is `wwContext.user.roles.includes('admin')` or `wwContext.user.roles.some(r => r.role_id === 'admin-role-id')`. With Auth0: roles are typically available at `wwContext.user['https://your-app.com/roles']`. Wrap multiple restricted items in a container and apply Conditional Rendering at the container level to keep your formula in one place.

Expected result: Admin-only menu items are hidden from non-admin users. The items are absent from the DOM entirely when conditional rendering is used.

6

Build a dynamic menu from a data collection

For menus whose items come from a database (e.g., a CMS navigation, product categories, or dynamically generated page sections): create a collection in the Data panel → + New → choose your data source (Supabase, REST API, etc.) → configure to fetch navigation items (e.g., a 'navigation_items' table with label and url columns). Now build your menu: add a Flexbox Container inside your header. Select the container → Settings panel → Repeat items → click the plug icon → bind to your navigation collection's data array. The first child element of the container becomes the template repeated for each item. Inside the template child, add a Text element and bind its text property to `item.label`. Add a workflow on click: Navigate → bind the URL to `item.url`. Add active-state styling using `if(item.url === window.location.pathname, 'nav-link-active', 'nav-link')` as the class binding. Change collection to update the nav without touching WeWeb.

Expected result: Navigation links are generated dynamically from your data source. Adding a row to the database navigation table automatically adds it to the menu on next page load.

7

Add a Side Menu for app-style navigation

For dashboard or app-style layouts, the Side Menu component provides a vertical navigation panel. In the Add element (+) panel → Navigation → Side Menu. The Side Menu is typically placed inside a layout that has the sidebar on the left and main content on the right. Create a Flexbox Container with flex-direction 'row'. Place the Side Menu inside the left child. Place your main content container inside the right child with Flex → Grow: 1 so it fills remaining space. In the Side Menu's Settings panel, configure navigation items the same way as the Top Navigation Bar — label and page destination pairs. At Mobile breakpoint, you will typically want to either hide the side menu entirely (set display to 'none') and show a bottom navigation or hamburger instead, or configure the side menu as an off-canvas drawer. The Side Menu component supports a collapsed/expanded state that can be toggled via a workflow: Add a workflow on click → Execute component action → Side Menu → Toggle.

Expected result: A vertical side menu appears alongside main content on Desktop. It can be toggled and collapses appropriately on Mobile.

Complete working example

mobile-menu-workflow.js
1// Injection point: Workflow → Custom JavaScript action
2// Use this action to handle advanced hamburger menu behavior
3// such as preventing body scroll when menu is open
4
5// Run this on hamburger icon click (after the Change variable value action)
6const isOpen = variables.mobileMenuOpen; // read current state
7
8if (isOpen) {
9 // Prevent body scroll when mobile menu is open
10 document.body.style.overflow = 'hidden';
11 document.body.style.position = 'fixed';
12 document.body.style.width = '100%';
13} else {
14 // Restore body scroll when menu closes
15 document.body.style.overflow = '';
16 document.body.style.position = '';
17 document.body.style.width = '';
18}
19
20// Return the state so subsequent workflow steps can use it
21return { menuIsOpen: isOpen };
22
23// ------------------------------------------
24// Active state formula for nav link class binding
25// Injection point: element class binding formula
26// ------------------------------------------
27// Paste this in the binding formula for a nav link's class property:
28//
29// [
30// 'nav-link',
31// wwContext.pageId === 'paste-your-page-id-here' ? 'nav-link-active' : ''
32// ]
33//
34// Find page IDs in the WeWeb editor URL when that page is selected:
35// https://editor.weweb.io/project/{project-id}/page/{page-id}

Common mistakes

Why it's a problem: Placing the header section directly on each page instead of using a linked section

How to avoid: Build the header once, then use multi-page sections (right-click Section → 'Turn into linked section'). Updating the header in one place updates it everywhere. Manually copying sections across pages leads to inconsistencies and maintenance headaches.

Why it's a problem: Assuming conditional visibility on menu items prevents unauthorized page access

How to avoid: Hiding a menu item only hides the link from the UI — a savvy user can still navigate directly to the URL. For actual access control, use Page settings → Access control to restrict pages to specific user groups (requires WeWeb Scale plan), and enforce RLS policies on your backend (Supabase Dashboard: Authentication → Policies).

Why it's a problem: Using separate navigation components on each page rather than linked sections, causing update delays

How to avoid: Convert your nav section to a linked section. Any design or content changes propagate to all linked pages automatically. This is essential for maintaining consistency in projects with 5+ pages.

Why it's a problem: Setting a fixed pixel height on the navigation bar that clips content on smaller screens

How to avoid: Use padding (top and bottom) to control nav bar height rather than a fixed height. Set padding-top and padding-bottom in the Styling panel using rem or px values, and let the content determine the overall height. This prevents clipping at different text sizes.

Best practices

  • Use multi-page linked sections for headers and footers — never manually copy navigation across pages
  • Always set navigation position to 'sticky' with z-index: 100 via Custom CSS so it stays visible during scroll
  • Add active-state class bindings to navigation links using wwContext.pageId to reflect the current page
  • Keep role-based menu visibility as UX enhancement only — enforce real security with Page settings → Access control and backend RLS
  • For mobile menus, change the Boolean variable to false when a menu link is clicked to auto-close the menu after navigation
  • Use the built-in Top Navigation Bar component for standard menus — it handles the hamburger collapse automatically without custom workflow logic
  • For dynamic menus from a collection, add a loading skeleton or fallback label so the nav doesn't flash empty while the collection fetches

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I'm building a navigation menu in WeWeb (a Vue.js-based no-code builder). I need a shared header that appears on all pages, with active link highlighting for the current page, and a hamburger menu on mobile. WeWeb uses multi-page linked sections for shared layouts and wwContext.pageId to identify the current page. Can you write the CSS class binding formula for active link states and the JavaScript for a mobile menu toggle that prevents body scroll?

WeWeb Prompt

In WeWeb, I have a navigation menu built with the Top Navigation Bar component. I want to add active-state highlighting so the current page's link shows a different color and background. I also want to add a 'Sign In' link that only shows when the user is not logged in, and an 'Account' link that only shows when they are logged in. Using Supabase Auth, how do I write the conditional rendering formulas for these nav items?

Frequently asked questions

How do I make a WeWeb navigation bar sticky so it stays at the top when scrolling?

Select the navigation bar or its parent Section → Styling panel → Layout → Position → Sticky. Set the Top offset to 0. Then open the Custom CSS field in the Styling panel and add z-index: 100 to ensure the nav bar appears above other page content when scrolling. If the nav is inside a Section, apply sticky positioning to the Section element, not just the inner container.

Can I have different navigation menus on different pages while still using linked sections?

Yes — with some planning. Create your base linked section and link it to most pages. For pages that need a different navigation (like a homepage with a transparent nav), exclude them from the linked section and design a separate header section on those pages. You can also use conditional rendering inside the linked section to show different menu items on different pages using the wwContext.pageId formula.

How do I add a dropdown submenu to a WeWeb navigation link?

The built-in Top Navigation Bar does not natively support dropdown submenus. Build a custom dropdown by: (1) adding a container next to your nav link positioned as absolute, initially hidden, (2) creating a Boolean variable 'dropdownOpen', (3) binding the dropdown container's display to that variable, (4) adding a workflow on the parent link's mouseenter to set dropdownOpen to true and on mouseleave to set it to false. Add a Time delay of 200ms before closing to prevent accidental closure.

Why does my navigation menu appear behind other page elements when sticky?

This is a z-index stacking issue. When the nav is sticky, other elements on the page with a higher z-index will appear on top of it. Add z-index: 1000 to the navigation section via Styling panel → Custom CSS field. If elements still appear on top, they may have explicit z-index values — open DevTools (F12) on your published page, click the offending element, and check its z-index in the Computed Styles tab.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.