Instantly share code, notes, and snippets.
Created
March 12, 2026 14:38
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save damiencarbery/8d2b77bcda754040727a8329eec3f867 to your computer and use it in GitHub Desktop.
Sticky Navigation - stick header area too - To set the navigation and header as sticky in GeneratePress the height of the header is needed for the navigation 'top' property. Also scroll to # anchors (less height of sticky header and sticky nav).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /* | |
| Plugin Name: Sticky Navigation - stick header area too | |
| Plugin URI: https://www.damiencarbery.com/ | |
| Description: To set the navigation and header as sticky in GeneratePress the height of the header is needed for the navigation 'top' property. Also scroll to # anchors (less height of sticky header and sticky nav). | |
| Author: Damien Carbery | |
| Version: 0.3.20260312 | |
| */ | |
| defined( 'ABSPATH' ) || exit; | |
| add_action( 'wp_footer', 'to_make_nav_sticky' ); | |
| function to_make_nav_sticky() { | |
| $module_active = null; // Different CSS for when GP Premium is active. | |
| $device_type = 'all'; // Slightly different JS depending on GP Premium Menu Plus Sticky Nav settings. | |
| // Check whether GP Premium plugin Menu Plus module active. | |
| if ( !function_exists( 'generate_menu_plus_get_defaults' ) ) { | |
| // Otherwise check whether GeneratePress is the active theme. | |
| if ( ! function_exists( 'generate_setup' ) ) { | |
| // If GeneratePress theme is not active, add a html comment for the site admin (so they know the plugin is working). | |
| if ( current_user_can('manage_options') ) { | |
| echo "\n<!-- Sticky Navigation: GeneratePress is not the active theme. This plugin is designed for GeneratePress theme. -->\n"; | |
| } | |
| return; | |
| } | |
| else { | |
| $module_active = 'generatepress'; | |
| } | |
| } | |
| else { | |
| $module_active = 'gp_premium'; | |
| // Merge stored data with default Menu Plus settings. | |
| $settings = wp_parse_args( | |
| get_option( 'generate_menu_plus_settings', array() ), | |
| generate_menu_plus_get_defaults() | |
| ); | |
| // If it is not set or is set to Off, add a html comment for the site admin (so they know the plugin is working). | |
| if ( !isset( $settings['sticky_menu'] ) || 'false' == $settings['sticky_menu'] ) { | |
| if ( current_user_can('manage_options') ) { | |
| echo "\n<!-- Sticky Navigation: GeneratePress Sticky Menu is set to 'Off'. Change to On, Mobile or Desktop for this plugin to work. -->\n"; | |
| } | |
| return; | |
| } | |
| if ( 'mobile' == $settings['sticky_menu'] ) { | |
| $device_type = 'mobile'; | |
| } | |
| if ( 'desktop' == $settings['sticky_menu'] ) { | |
| $device_type = 'desktop'; | |
| } | |
| if ( 'true' == $settings['sticky_menu'] ) { | |
| $device_type = 'all'; | |
| } | |
| } | |
| // GP Premium adds body classes for Sticky Nav. | |
| if ( 'gp_premium' == $module_active ) { | |
| ?> | |
| <style> | |
| /* GP Premium sticky navigation styling. */ | |
| body.both-sticky-menu #masthead { top: 0; } | |
| body.both-sticky-menu #masthead, body.both-sticky-menu #site-navigation { position: sticky; z-index: 100; } | |
| @media (max-width: 768px) { | |
| body.mobile-sticky-menu #masthead { top: 0; } | |
| body.mobile-sticky-menu #masthead, body.mobile-sticky-menu #site-navigation { position: sticky; z-index: 100; } | |
| } | |
| @media (min-width: 769px) { | |
| body.desktop-sticky-menu #masthead, body.both-sticky-menu #masthead { top: 0; } | |
| body.desktop-sticky-menu #masthead, body.desktop-sticky-menu #site-navigation { position: sticky; z-index: 100; } | |
| } | |
| </style> | |
| <?php | |
| } | |
| // There's no extra body classes so we can target #masthead and #site-navigation directly. | |
| if ( 'generatepress' == $module_active ) { | |
| ?> | |
| <style> | |
| /* GeneratePress sticky navigation styling. */ | |
| #masthead { top: 0; } | |
| #masthead, #site-navigation { position: sticky; z-index: 100; } | |
| @media (max-width: 768px) { | |
| #masthead { top: 0; } | |
| #masthead, #site-navigation { position: sticky; z-index: 100; } | |
| } | |
| @media (min-width: 769px) { | |
| #masthead { top: 0; } | |
| #masthead, #site-navigation { position: sticky; z-index: 100; } | |
| } | |
| </style> | |
| <?php | |
| } | |
| ?> | |
| <script> | |
| // Get the height of the #masthead element (the header with logo) and set the 'top' property of #site-navigation to that height. | |
| document.addEventListener("DOMContentLoaded", function(event) { | |
| const device_type = '<?php echo $device_type; ?>'; | |
| if ( ( 'all' == device_type ) || | |
| ( 'mobile' == device_type && screen.width <= 768 ) || | |
| ( 'desktop' == device_type && screen.width > 768 ) ) { | |
| const header_el = document.getElementById( 'masthead' ); | |
| // If the user is logged in we must include the height of the admin bar. | |
| var wpAdminBarHeight = 0; | |
| const wpAdminBar = document.getElementById( 'wpadminbar' ); | |
| if ( wpAdminBar ) { | |
| wpAdminBarHeight = wpAdminBar.offsetHeight; // offsetHeight is not ideal as it excludes margin top/bottom. | |
| } | |
| //console.log( 'wpAdminBarHeight:', wpAdminBarHeight ); | |
| header_el.style.top = wpAdminBarHeight + 'px'; | |
| const site_nav = document.getElementById( 'site-navigation' ); | |
| site_nav.style.top = ( header_el.offsetHeight + wpAdminBarHeight ) + 'px'; | |
| //console.log( '#masthead top = ', header_el.offsetHeight ); | |
| //console.log( '#site-navigation top = ', site_nav.style.top ); | |
| // Add the classes that the GP Premium Menu Plus stickUp() JS would add. | |
| site_nav.classList.add( 'is_stuck', 'navigation-stick', 'navigation-clone', 'sticky-navigation-transition' ); | |
| } | |
| }); | |
| // Scroll to anchor element and reduce scroll distance by height of header and nav. | |
| document.addEventListener('click', function (event) { | |
| const linkTarget = event.target.getAttribute('href'); | |
| // Verify that link is not null and begins with contains anchor url (begins with #). | |
| if (! linkTarget ) return; | |
| if (! linkTarget.startsWith( '#' ) ) return; | |
| // Don't follow the link | |
| event.preventDefault(); | |
| targetID = linkTarget.substring( 1 ); | |
| if (! targetID ) return; | |
| const targetDiv = document.getElementById( targetID ); | |
| if (! targetDiv ) return; // Quit if target anchor cannot be found. | |
| const header_el = document.getElementById( 'masthead' ); | |
| const site_nav = document.getElementById( 'site-navigation' ); | |
| // Scroll to target Div less height of header and nav. | |
| window.scrollTo({ behavior: 'smooth', top: targetDiv.offsetTop - header_el.offsetHeight - site_nav.offsetHeight }) | |
| }, false); | |
| </script> | |
| <?php | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment