Use CSS to Fix a Navbar to the Top or Bottom Without JavaScript
Want a CSS fixed navbar that stays at the top (or bottom) of the screen while visitors scroll, without loading a single line of JavaScript? Modern CSS makes it easy. Years ago, sticky menus needed jQuery scroll listeners that recalculated offsets on every scroll event. Today one or two CSS properties do the job, they work in every modern browser, and they don’t slow your page down. Here’s how to fix a navbar to the top or bottom of the page with pure CSS, and how to avoid the common problems.

Quick answer: For a top navbar, use position: sticky; top: 0; z-index: 100; on the <nav>. It stays in the page flow and sticks once you scroll past it. For a bottom bar, use position: fixed; bottom: 0; left: 0; right: 0; and add bottom padding to the <body> so the bar doesn’t cover your content. No JavaScript is needed for either.
Table of Contents
Sticky vs fixed: which CSS position should you use?
CSS gives you two ways to pin a navigation bar to the screen:
position: fixedremoves the element from the normal page flow and pins it to the viewport. It never moves, but the content behind it slides underneath, so you must reserve space for it with padding.position: stickykeeps the element in the normal flow until you scroll to a set offset (such astop: 0), then it sticks. Because it still takes up space, nothing hides behind it and you don’t need any padding fix.
For most sites, sticky is the better choice for a top navbar, and fixed is the better choice for a bottom bar. Both are supported in all current versions of Chrome, Edge, Firefox and Safari, as the MDN position reference shows.
How to fix a navbar to the top with CSS
Method 1: position: sticky (recommended)
Here’s a simple header navigation:
<nav class="topnav">
<a href="/">Home</a>
<a href="/blog/">Blog</a>
<a href="/about/">About</a>
</nav>Add this CSS to make it a sticky navbar:
.topnav {
position: sticky;
top: 0;
z-index: 100;
background: #142540;
padding: 12px 16px;
}
.topnav a {
color: #fff;
margin-right: 16px;
text-decoration: none;
}That’s it. The navbar scrolls normally with any logo or banner above it, then locks to the top of the screen. The z-index keeps it above images and other content, and the solid background stops text showing through it.
Method 2: position: fixed
If you want the navbar pinned from the very first pixel, use position: fixed:
.topnav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
height: 56px;
}
body {
padding-top: 56px; /* same as the navbar height */
}The padding-top on the body is essential. Without it, the first 56 pixels of your page (usually the heading) will hide behind the navbar.
How to fix a navbar to the bottom with CSS
A bottom navigation bar works well on mobile, where thumbs reach the bottom of the screen more easily. Use position: fixed with bottom: 0:
.bottomnav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 100;
display: flex;
justify-content: space-around;
background: #142540;
padding: 10px 0;
padding-bottom: calc(10px + env(safe-area-inset-bottom));
}
body {
padding-bottom: 64px;
}Two details matter here:
- Body padding:
padding-bottomon the body stops the bar from covering your footer and the last lines of content. - Safe area:
env(safe-area-inset-bottom)adds extra space above the home indicator on iPhones and gesture-navigation Android phones, so your links stay tappable. For it to work, addviewport-fit=coverto your viewport meta tag:<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">. See env() on MDN.
Add icons with a lightweight icon set (here’s how to add Font Awesome icons) to make a mobile-app style bottom menu.
Show the bottom bar only on mobile
A bottom bar can feel odd on a wide desktop screen. Use a media query to show it only on small screens:
.bottomnav { display: none; }
@media (max-width: 768px) {
.bottomnav { display: flex; }
body { padding-bottom: 64px; }
}Fix anchor links hidden under a sticky header
When someone clicks a jump link (like a table of contents link), the browser scrolls the heading to the very top, where it hides under your fixed header. One line of CSS fixes this:
html {
scroll-padding-top: 70px; /* navbar height plus a little space */
}scroll-padding-top tells the browser to leave that much room when scrolling to an anchor. It’s another job that used to need JavaScript.
Why position: sticky sometimes doesn’t work
If your sticky navbar won’t stick, check these common causes:
- No offset set. Sticky needs
top,bottom,leftorright. Withouttop: 0, nothing happens. - A parent has overflow set. If any ancestor has
overflow: hidden,overflow: autooroverflow: scroll, the navbar sticks inside that box instead of the page. Useoverflow: clipon the parent instead if you only need to hide overflow. - The parent is too short. A sticky element only sticks within its parent. If the
<nav>sits inside a short<header>, it scrolls away with the header. Make the header itself sticky, or move the nav outside it. - Flexbox or grid stretching. In a flex or grid container, add
align-self: flex-start(oralign-self: start) so the element isn’t stretched to the full height.
Is a fixed navbar good for SEO and page speed?
Pure CSS sticky headers are better for performance than JavaScript versions. They don’t run code on every scroll, which keeps the page smooth and helps Interaction to Next Paint (INP), one of Google’s Core Web Vitals. Using sticky instead of switching an element to fixed with JavaScript also avoids sudden layout jumps that hurt Cumulative Layout Shift.
Keep the bar slim, though. A tall fixed header takes up a lot of a phone screen and can annoy readers. Around 50–60 pixels is plenty. If your site uses a lightweight framework like Chota CSS, the same CSS works with its nav component. On WordPress, many themes, including Kadence and Astra, have a sticky header option built into the Customizer, so check there before adding your own code. If you do add custom CSS, here’s how to add custom CSS in WordPress.
Frequently asked questions
How do I make a navbar fixed to the top without JavaScript?
Add position: sticky; top: 0; z-index: 100; to the navbar. Or use position: fixed; top: 0; width: 100%; and add padding-top to the body equal to the navbar’s height.
What is the difference between sticky and fixed in CSS?
A fixed element is always pinned to the viewport and removed from the page flow. A sticky element scrolls normally until it reaches its offset, then sticks, and it keeps its space in the layout.
Why is my fixed navbar covering my content?
position: fixed takes the navbar out of the page flow, so content moves up underneath it. Add padding-top (for a top bar) or padding-bottom (for a bottom bar) to the body, equal to the bar’s height. Or switch a top navbar to position: sticky.
Does position: sticky work on all browsers?
Yes. It works in all current versions of Chrome, Edge, Firefox and Safari, on desktop and mobile. Only very old browsers such as Internet Explorer lack support.
Can I fix a navbar to both the top and the bottom?
Yes. Use a sticky top navbar for the main menu and a fixed bottom bar for mobile shortcuts. Just remember the body padding for the bottom bar, and keep both bars slim so readers still have room for content.






