How to Create a Fixed Header in WordPress

You may have noticed that a lot of popular WordPress sites are using what’s known as a fixed header. Adding a fixed header to your WordPress theme can make navigating your site easier and improve user experience, so we decided to hook it up. I’ve been asked a few times how we accomplished this, so I figured it might make a good topic for a blog post.

If you’re familiar with CSS, creating a fixed header, which is also known as a sticky header, is pretty straightforward. Because we build almost everything with the Genesis Framework, my code will be geared towards that, but it could be easily modified to work with any WordPress theme.

The first thing you need to do to create a fixed header is assign a fixed position to your header element. If you’re using Genesis 2.0, the code to do this should be almost identical to what we’re publishing.

If you’re using an older version of Genesis or another WordPress theme, this code will need to be modified slightly. For instance, on an older version of Genesis you would target #header rather than .site-header. In other themes your header’s selector could be just about anything, but searching through the code to find it shouldn’t take too long.

Get Your Fixed Header Positioned Correctly:

Site Header
---------------------------------------------------------------------------------------------------- */
/* This is where the magic happens. You need
 * to assign a fixed position in order for
 * everything else to work correctly.
--------------------------------------------- */
.site-header {
	position: fixed;
	top: 0;
	width: 100%;
	z-index: 2000;

/* This will ensure your site looks correct
 * when the admin bar is displaying.
--------------------------------------------- */
body.admin-bar .site-header {
	top: 32px;

Once you’ve done that, you should have a functional sticky header in your WordPress theme. Unfortunately, everything will still look a bit screwed up at this point. In order to make sure your theme’s fixed header looks good and functions correctly, you need to figure out how tall your header is in pixels.

In Genesis, most of the newer child themes have a header with a fluid height. This makes it much easier to adapt your CSS as the viewport scales down. You technically could assign a fixed height to your header, but then you’ll probably have to modify it via media queries in order for the mobile version of your site to function correctly.

This isn’t usually necessary and doesn’t follow the Mobile First methodology. Your best bet is to let the header inherit its height from the elements inside it. These include the logo and in our case the primary site navigation.

For our site, the tallest element in the header is the logo, which has a max-height of 81px. The height for the logo was calculated by figuring out the height of the individual navigation items including top and bottom padding. You’ll likely need to take a similar approach on your site, depending on how your header is structured.

If you’re afraid of math, you could also do this visually by playing with the padding on your site’s body (lawl) until it matches the header element’s height and everything looks correct. In any event, once you’ve figured out the height of your WordPress theme’s sticky header, you’ll need to…

Add the Correct Padding to the Body for your Fixed Header

Body Element 
---------------------------------------------------------------------------------------------------- */

/* This Should Be Equal to the Height of your
 * fixed header bar.
--------------------------------------------- */
body {
  	padding-top: 81px;

If you’re rocking Genesis 2.0 you should be pretty much all set at this point. If not, you might have some issues with clearing your floats. If your site looks screwed up or you need to assign overflow: hidden; to your header, you probably need to add some float clearing.

I feel like a broken record, but the latest version of Genesis really does kick ass. They’ve added the following CSS after the standard reset to make clearing floats the old fashioned way obsolete.

Shiny New Float Clearing Awesomeness

/* Float Clearing
--------------------------------------------- */

address:before, address:after,
article:before, article:after,
aside:before, aside:after,
audio:before, audio:after,
blockquote:before, blockquote:after,
canvas:before, canvas:after,
dd:before, dd:after,
div:before, div:after,
dl:before, dl:after,
fieldset:before, fieldset:after,
figcaption:before, figcaption:after,
figure:before, figure:after,
footer:before, footer:after,
form:before, form:after,
header:before, header:after,
hgroup:before, hgroup:after,
hr:before, hr:after,
main:before, main:after,
output:before, output:after,
pre:before, pre:after,
section:before, section:after,
table:before, table:after,
tfoot:before, tfoot:after,
video:before, video:after,
.clearfix:before, .clearfix:after {
 	content: " ";
	display: table;

.clearfix:after {
	clear: both;

You could modify your theme to follow a similar approach, or you could bite the bullet and make the move to the Genesis Framework. It’ll make your life easier, I promise.

Well, that about wraps this post up I think. If you have any trouble implementing your fixed header or if you have suggestions for improving ours, please let us know in the comments!


  1. Daniel

    I attempted to make a sticky header, but the script did not work.

    I tried:
    .site-header {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 2000;

    There was no sticky header. Specifically, I want my site title and top menu bar to be sticky. I only have a premium WordPress account and cannot yet afford a Business Account to use plug-ins. Can you provide any ideas? Thanks!

    1. Ozzy Rodriguez

      Hi Daniel,

      I just tested the CSS snippet on your site and it worked, so it would seem as though it wasn’t added correctly. Make sure you’re saving it off before refreshing your site.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.