Updated 28-Jun-2024
In the attempt to remove as much of javascript as possible, certainly not relying on jquery
and its ilk, we need a CSS-only sticky header and/or footer.
This is normally quite straightforward. However, the trick comes when logged into WordPress and the Adminbar is present.
If only the #mobile-header
, .site-header
, #site-navigation
, or #masthead
is needed for sticky, then voila:
/* sticky header */
#mobile-header,
#masthead {
position: -webkit-sticky;
position: sticky;
top: 0px;
}
Note that -webkit-sticky
is needed to support Safari browsers before v.13 (Sep 2019).
Currently for the themes in GeneratePress that we are using, the #mobile-header
and masthead
are what works for us.
Adminbar Sticky
The Adminbar is either 32px or 64px in height depending on @media query
. Therefore if the Adminbar is always present, simply add that many pixels to the top:
directive.
/* sticky header */
#mobile-header,
#masthead {
position: -webkit-sticky;
position: sticky;
top: 32px;
}
@media all and (max-width:782px) {
#mobile-header,
#masthead {
top: 46px;
}
}
The problem comes when there may be an admin bar, or may not be.
Sticky Adminbar Workarounds
There are several approaches to this, since CSS itself cannot detect the presence or absence of a class or id.
- Javascript (what we are trying to avoid)
- Hide the Adminbar altogether (cure is worse than the disease)
- Move Adminbar to the bottom (learning curve and all other sites have it at the top)
- Modify the
header.php
template to inject classes into the body based on logged-in status, then inject CSS via a function - A cleaner approach to 4. which adds a spacer div into
header.php
and styles it. - Add a header spacer div between the header and the content, and recalculate widths of that if Adminbar is present
- CSS Only
The first option of Javascript is what we are trying to avoid. The current GeneratePress theme loads jQuery when the sticky header is enabled (adding insult to injury).
The second two options are obvious work-arounds / hacks by either hiding or moving the Adminbar.
The fourth option requires editing a PHP template in the theme or a child theme. Not too difficult but if there is a non-PHP approach, that would be better. Note that the page linked above goes a bit nuts and adds the CSS via a function added to functions.php
. This aims to be a PHP-only approach. Fair enough.
The fifth option adds a spacer div and immediately styles it, but that styling is limited to one size of the Adminbar, not both. In this case a @media query
and css classes are needed.
The sixth option is the same as the fifth, except that the div is present whether logged-in or not and simply styled using blocks of css. This is the cleverer of the options above. It also means we can avoid editing the WordPress templates and/or PHP files directly, if we are using builder themes or theme frameworks that support hooks and allow us to inject div
s where we wish (namely between the header and body).
The seventh option is of course the obvious choice. No PHP or additional <div>s
needed.
CSS for Sticky Header with Adminbar
The key is that the class .admin-bar
is added to the body when logged in. So if present, we add the
/* sticky header */
#mobile-header,
#masthead {
position: -webkit-sticky;
position: sticky;
top:0;
}
.admin-bar #mobile-header,
.admin-bar #masthead {
top: 32px;
}
@media screen and (max-width: 782px) {
.admin-bar #mobile-header,
.admin-bar #masthead {
top:46px;
}
}
There are a few tweaks we add for mobile.
- For some sizes of the Adminbar,
position:absolute;
is added, but that breaks our sticky, so we have to addposition:fixed;
. We do this with the#wpadminbar
id. - Also the
.main-title
(our text logo) and h1s are a bit big for this size, based on our standard desktop font sizes, so we change their sizes to30px
.
/* sticky header & wpadminbar support */
#mobile-header,
#masthead {
position: sticky;
position: -webkit-sticky;
position: -top:0;
}
.admin-bar #mobile-header,
.admin-bar #masthead {
top: 32px;
}
@media screen and (max-width: 782px) {
.admin-bar #mobile-header,
.admin-bar #masthead {
top: 46px;
}
#wpadminbar {
position: fixed;
}
.main-title, h1 {
font-size:30px;
}
}
For mobile-first (if the adminbar is used more often when on mobile), reverse the order of the adminbar position sizes and use min-width:783px
instead of max-width
.