How to make a header in HTML
Wrap the top of your page (logo, site name, main menu) in a <header> element. It is a block box with no default look, so a few lines of CSS turn it into a bar:
margin-inline-end: auto on the logo pushes the menu and the button to the far end of the bar. Remove the <style> element and you still have a header: it is the tag that makes it one, not the dark background.
header vs head vs h1
Three names that sound alike and do different jobs:
| Element | Where | Visible | How many |
|---|---|---|---|
<head> | Directly inside <html>, before <body> | No: holds <title>, <meta>, <link> | Exactly one |
<header> | Inside <body> | Yes: intro content of a page or section | Any number |
<h1> to <h6> | Anywhere in <body> | Yes: a heading | Any number |
The <head> below sets the page title that a browser shows in its tab. Everything you can see in the preview comes from <body>:
A header often contains a heading, but it does not have to, and a heading does not need a header around it.
Headers inside articles
<header> introduces its nearest article or section, not only the page. A blog post list where each post has its own header is valid and common:
For screen readers, only the page-level header (one that is not inside article, aside, main, nav or section) becomes the banner landmark. The article headers are plain groups, so you do not end up with several banners.
Sticky header
position: sticky keeps the header at the top while the content under it scrolls. Scroll inside the box below:
Three details make it work: top: 0 (sticky does nothing without an offset), a background color (otherwise the rows show through), and z-index so positioned content does not paint over it. On a real page the scrolling box is the page itself, so the header sits directly in <body>.
A header with position: fixed also stays put, but it leaves the page flow, so the content slides under it and needs padding at the top. Sticky keeps its space in the layout.
What can go in a header
A header can contain almost any content: headings, a logo image, a <nav>, a search form, a button. It cannot contain another <header> or a <footer>, and it cannot sit inside a <footer>, an <address> or another <header>.
<header>
<a href="/"><img src="logo.svg" alt="Acme home"></a>
<nav aria-label="Main">...</nav>
<form role="search">...</form>
</header>
When the logo is a link to the home page, its alt text should say where the link goes ("Acme home"), because that is what a screen reader announces.
Common mistakes
- Confusing
<header>with<head>. Metadata goes in<head>; visible content never does. - Using
<header>for every heading. A heading alone does not need a header wrapper. Use<header>when there is a group of intro content. - A sticky header with no background. The page text scrolls visibly through it. Set a
background. - Sticky that does not stick. An ancestor with
overflow: hiddenoroverflow: autobecomes the scroll box for sticky, so the header sticks inside that box (or not at all). Check the ancestors. - Putting the site menu in a
<div>inside the header. Use<nav>so screen reader users can jump to it.
Frequently Asked Questions
What is the header tag in HTML?
<header> is a semantic element for introductory content: a site logo and menu at the top of the page, or the title and byline at the top of an article. It is a normal block box with no default styling.
What is the difference between head and header in HTML?
<head> is the invisible part of the document with the <title>, <meta> tags and stylesheet links, and there is exactly one. <header> is visible content inside <body>, and a page can have several.
Can a page have more than one header element?
Yes. A page usually has one site header, and each <article> or <section> can have its own <header> for its title and meta information. Only a header that is not inside article, aside, main, nav or section counts as the page banner for screen readers.
Should the nav go inside the header?
It can, and it often does when the main menu sits at the top of the page. Putting <nav> outside <header> is also valid; choose whatever matches your layout.
How do I make a header stay at the top when scrolling?
Give it position: sticky; top: 0; plus a background color and a z-index, so content scrolls underneath it. Sticky works only while the header's parent is taller than the header, and an ancestor with overflow: hidden stops it from sticking to the page.