Skip to content
New: Customize your theme with an AI assistant. Read the guide

Header & Announcement

Files: src/config/config.toml, src/config/menu.en.json, src/i18n/en.json, page frontmatter · Skill level: Beginner

Every header bar has the logo, the menu, and a button (“Get a free quote”). On small screens the menu links and the button move into a slide-in panel, opened with a Menu button. Around the bar, Ecozen has four header layouts with different contact rows, backgrounds, and an optional announcement strip.

In the Tina edition, these settings are under Site settings at /admin/, and the words under Interface labels. In the Sanity edition, they are in the Studio under Site settings > Settings, and the words under Interface labels in each language.

Choose A Header Layout

src/config/config.toml
[settings.header]
layout = "classic" # classic | transparent | floating | promo
LayoutWhat it looks likeDemo page
classicA dark top bar with your email, phone, opening hours, social icons, and the language switch, above a white header bar. The default, used by inner pages/home-two/
transparentSits over the photo at the top of the page, with white links and the light logo (logoAlternate). A thin info row above it shows your phone, hours, social icons, and the language switch, and a round phone icon sits next to the button. The info row is hidden on small screens. Once the info row has scrolled away, the bar turns solid/, /services/
floatingA white bar with rounded corners, set in from the edges over the photo at the top of the page. It stays set in while you scroll/home-three/
promoA citrus announcement strip (see below), then a white bar with your phone number and opening hours beside the button (on wide screens)/home-four/

One page, another layout. Add headerLayout to the page’s frontmatter. It wins over [settings.header] layout:

---
headerLayout: "promo" # classic | transparent | floating | promo
title: "EV charging and home batteries"
---

Each demo homepage sets its own. The transparent and floating layouts sit over the first section, so use them only on pages that open with a full-width photo or dark band, such as a photo or panel hero. Three routes, index.astro, home-three.astro, and services/index.astro, also pass headerTransparent={true} to <Base>; it means the same as headerLayout: "transparent", and a page’s headerLayout wins over it (/home-three/ sets floating). npm run astro-check reports a misspelled value in files that have a schema.

The contact details come from [settings.contactInfo] in config.toml, the social icons from the first four links in src/config/social.json, and the opening hours can be translated with footer.hoursText in the i18n files (see Footer).

Language switch: in the top bar for classic, in the main bar for floating and promo, and for transparent in the info row on large screens and the main bar below them; it lists the language names from src/config/language.json, and in the main bar, phones show only its icon.

The Header Button

[settings.navigationButton]
enable = true
label = "" # empty uses navigation.buttonLabel from src/i18n/en.json ("Get a free quote")
url = "/contact/"

To change the words in every language, edit navigation.buttonLabel in each file in src/i18n/. On small screens this button is hidden; the menu panel has its own button (see below).

[settings]
stickyHeader = true # the header bar stays at the top while you scroll

Only the header bar sticks. The announcement strip, the classic top bar, and the transparent info row sit above it and scroll away with the page. When the bar reaches the top of the window, only its colours change: classic and promo get a slightly see-through white background, and transparent turns solid. Its size and position never change, so nothing jumps while you scroll.

Set stickyHeader = false to let the header scroll away with the page. The floating bar is pinned to the top in both cases.

The Announcement Strip

A citrus line at the very top of the page, for an offer or a seasonal campaign. It ends with an arrow link and a close button. When a visitor closes it, their browser remembers that until the text changes.

The promo layout always shows it. The classic layout shows it when you turn it on:

[settings.announcementBar]
enable = true # also show the strip above the classic header
label = "" # empty uses header.announcement from src/i18n/en.json

The text is one line of Markdown. Its first link becomes the arrow link at the end, for example Free roof survey this month. [Book yours](/contact/). The text comes from, in this order:

  1. headerAnnouncement in the page’s frontmatter, as /home-four/ does:

    headerAnnouncement: "Home charger fitted from $1,190 this month, with off-peak setup included. [Get a quote](/contact/)"
  2. [settings.announcementBar] label in config.toml, the same in every language

  3. header.announcement in each file in src/i18n/

For a site in several languages, leave label empty and use the i18n files, or headerAnnouncement in each language’s page file. The close button’s screen-reader name is header.announcementClose.

The transparent and floating layouts never show the strip.

The Mobile Menu Panel

On phones and tablets, the menu links are hidden and the Menu pill button opens a panel from the right (from the left on right-to-left pages) with, from top to bottom:

  • a round close button and your logo
  • a short description
  • the menu links. Dropdowns open as lists inside the panel, with a plus or minus sign, and a group inside a dropdown opens its own list. The Services mega menu shows each group’s name as a small label, its links with their icons, and the mega menu’s cta card with its button (see Menus)
  • your address, phone, and email from [settings.contactInfo]. The phone and email are links
  • up to four social icons from src/config/social.json
  • a button, full width on phones

On large screens the Menu button and the panel are hidden, because the menu links sit in the header bar. Developers can show the button there too with hideOffcanvas={false} on <Base> in a page route; the panel then opens without the menu links.

The description and the button are set in config.toml:

[settings.headerOffcanvas]
enable = true
description = "" # empty uses headerOffcanvas.description from the i18n files
[settings.headerOffcanvas.button]
enable = true
label = "" # empty uses headerOffcanvas.buttonLabel
url = "/contact/"

The labels of the panel are in the i18n files: navigation.menuLabel is the text of the Menu button (“Menu”), navigation.closeMenu is the screen-reader name of the close button (“Close menu”), navigation.mainLabel names the menu for screen readers (“Main”), and widgets.offcanvasLabel names the panel (“Site menu”). Change them in every language file. navigation.languageLabel is the screen-reader name of the language switch.

The panel is a native <dialog>. A closed panel is hidden from the keyboard, so Tab never lands on links you can’t see. Every link and button in the header and the panel shows a visible focus ring.

Desktop Dropdowns And The Mega Menu

On large screens, every dropdown and the Services mega menu open in one shared panel under the header. When you move from one menu item to the next, the panel changes its size and content instead of closing and opening again, and a small pointer follows the item.

  • The Services mega menu shows its link groups as text only. When there are two or more groups, the first one is in large type, with an arrow that appears on hover, and the others are compact lists. The links’ icons and descriptions are not shown here. On screens 1320px and wider, the cta card sits on the right as a mint pane with a photo, title, text, and button. An optional bar along the bottom adds a line of text, a link, and your phone number.
  • A dropdown, like Pages, is one list. An item that has its own links, like Home, shows a small arrow and opens them in a card beside it, a flyout. Flyouts open on hover or with a click.
  • Mouse: hovering a menu item opens its panel, and moving away closes it after a short pause. A click also opens and closes it.
  • Keyboard: Enter, Space, or ↓ on a menu item opens the panel and moves to its first link, and ↑ to its last. Inside the panel, ↑ and ↓ move between links, → opens a flyout and ← closes it, Home and End jump to the first and last link, Esc closes a flyout or the panel and returns to the item that opened it, and Tab moves on.
  • Reduced motion: for visitors who ask for less motion, the panel only fades, without sliding or resizing.

On small screens, the menu lives in the mobile menu panel described above.

You don’t need to touch any code to use it: the panel is built from the same menu file (see Menus). Developers find it in src/layouts/components/global/header/: NavStage.astro (the panel and its script), NavStageDropdown.astro and NavStageList.astro (a dropdown’s list and its flyouts), and NavStageMega.astro (the mega menu’s groups, photo pane, and bottom bar).

Files For Developers

All in src/layouts/components/global/header/: Header.astro picks the layout, TopBar.astro draws the contact row (variant="bar" for classic, variant="overlay" for transparent), AnnouncementStrip.astro draws the strip, Navbar.astro and MenuItem.astro draw the menu, LanguageSwitcher.astro is the language switch, NavbarToggler.astro is the Menu button, and DropdownMenu.astro and MegaMenu.astro are the dropdowns and the Services menu inside the mobile panel. The panel itself is src/layouts/components/widgets/Offcanvas.astro, with its content in HeaderOffcanvasContent.astro in the same folder. Their styles are in src/styles/navigation.css.

The links, the Services mega menu, and the dropdowns come from src/config/menu.<language>.json. See Menus and Navigation.

Do It With AI

Set the header to the [classic | transparent | floating | promo] layout in [settings.header] of
src/config/config.toml, and remove headerLayout from the homepage files I keep (or set it to the
same value). Set the header button in config.toml to "[URL]" and change navigation.buttonLabel in
every file in src/i18n/ to "[LABEL]", translated. Write this announcement in header.announcement in
every i18n file: "[TEXT]" linking to "[URL]", and turn on [settings.announcementBar] if I use classic.
Type something to search...