Implement Sticky Header on Top of Website
Description
We need to add a sticky (fixed) header to the top of the website so that the navigation bar remains visible as users scroll down the page. This will improve site usability and enhance the user experience, especially on long pages.
Notes
If using custom CSS/JS, ensure it's added via child theme or via proper enqueuing.
Proposal
Reference from original website:
https://github.com/user-attachments/assets/be8ace22-723a-409e-94d9-efc18314185d
Task
- [x] Add custom-sticky.js file
- [x] Add the css to the style.css file
- [x] Add functions to the functions.php file
- [x] Add Limitations
- [x] Change the color of social links on scrolling
- [x] Change the site logo on scrolling
- [x] Add Screencast of Demo
- [x] Change the color of the drop down menu on scrolling
Files added (in the child theme)
-
custom-sticky.js: This new file contains the JavaScript logic that detects scroll position and adds/removes the is-sticky class to your header. It also dynamically adjusts the padding-top of the body to prevent content from jumping. -
style.css: This file now includes the CSS rules for the is-sticky class, defining how the header looks and behaves when it's fixed at the top of the screen. -
functions.php: This file ensures that your new custom-sticky.js file and your style.css file are correctly loaded by WordPress.
TASK: Add custom-sticky.js file
Steps to Implement:
-
Create JavaScript File:
- Navigate to:
wp-content/themes/astra-child/ - Create a new file named:
custom-sticky.js
- Navigate to:
-
Add JavaScript Code:
- Open
custom-sticky.jsand paste the following code and save the file:
- Open
document.addEventListener('DOMContentLoaded', function () {
const header = document.querySelector('.ast-main-header-wrap');
if (!header) return;
function updateStickyHeader() {
const scrollY = window.scrollY || window.pageYOffset;
if (scrollY > 50) {
header.classList.add('is-sticky');
} else {
header.classList.remove('is-sticky');
}
}
window.addEventListener('scroll', updateStickyHeader);
updateStickyHeader(); // Run on load in case page is already scrolled
});
-
Verify the File Is Active:
- Go to WordPress Dashboard > Appearance > Theme File Editor.
- Select the Astra Child theme.
- Confirm
custom-sticky.jsis listed.
TASK: Add the css to the style.css file
WordPress Dashboard > Appearance > Customize > Additional CSS (Left sidebar) > Paste the following CSS in the editor > Publish
OR
Admin Dashboard > Themes > Theme File Editor > select style.css (Make sure the astra-child is selected) > paste the following CSS > update file
/*
* Add these styles to your astra-child/style.css file
* This replaces any previous sticky header CSS.
*/
/* Base styles for the main header wrap */
.ast-main-header-wrap {
/* Ensure smooth transitions for all properties that change */
transition: all 0.3s ease-in-out;
/* --- KEY CHANGE HERE --- */
/* Set initial background color to transparent */
background-color: transparent;
/* Ensure it has a z-index even when not sticky, to prevent issues with other elements */
z-index: 99; /* Lower than sticky state, but still above most content */
position: sticky; /* Fallback for modern browsers */
/* Optional: If your logo or menu items are not visible on a dark background initially,
you might need to set their initial color here. For example: */
/*
color: #ffffff; // Example: white text/icons initially if header is over a dark hero section
*/
}
/* Styles for the sticky header when the 'is-sticky' class is applied by JavaScript */
.ast-main-header-wrap.is-sticky {
position: fixed; /* Makes the header stick to the viewport */
width: 100%; /* Ensures the header spans the full width of the viewport */
backdrop-filter: blur(5px); /* Optional: for frosted glass effect */
transform: translateZ(0); /* Hardware acceleration */
/* Semi-transparent white background when sticky */
background-color: rgba(255, 255, 255, 0.9); /* 0.9 for 0.X as a good default */
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); /* Adds a more pronounced shadow */
}
/* Styles for text and icons within the sticky header */
/* Target common elements like links (menu items, social links) and icons */
.ast-main-header-wrap.is-sticky .main-header-menu a, /* For main menu links */
.ast-main-header-wrap.is-sticky .ast-builder-menu-element a, /* For builder menu links */
.ast-main-header-wrap.is-sticky .ast-social-stack a, /* For social links */
.ast-main-header-wrap.is-sticky .ast-social-stack svg, /* For social icons (SVG) */
.ast-main-header-wrap.is-sticky .ast-social-stack i, /* For social icons (FontAwesome/i tags) */
.ast-main-header-wrap.is-sticky .site-title a, /* For site title link */
.ast-main-header-wrap.is-sticky .site-description { /* For site description */
color: #333333 !important; /* Change text/icon color to dark gray */
/* Add transition for color property for smooth change */
transition: color 0.3s ease-in-out;
}
/* Ensure the default colors also have a transition for when the sticky class is removed */
/* This ensures a smooth transition back to the initial (potentially different) color */
.ast-main-header-wrap .main-header-menu a,
.ast-main-header-wrap .ast-builder-menu-element a,
.ast-main-header-wrap .ast-social-stack a,
.ast-main-header-wrap .ast-social-stack svg,
.ast-main-header-wrap .ast-social-stack i,
.ast-main-header-wrap .site-title a,
.ast-main-header-wrap .site-description {
transition: color 0.3s ease-in-out;
}
/* Prevent layout shift by reserving space */
body {
padding-top: 0;
transition: padding-top 0.3s ease-in-out;
}
/* Logo color change on sticky */
.ast-main-header-wrap .site-logo-img img,
.ast-main-header-wrap .custom-logo {
transition: filter 0.3s ease-in-out;
}
.ast-main-header-wrap.is-sticky .site-logo-img img,
.ast-main-header-wrap.is-sticky .custom-logo {
filter: brightness(0) saturate(100%) invert(20%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(20%) contrast(100%);
}
/* Social icons color change on sticky */
.ast-main-header-wrap .ast-header-social-1-wrap svg,
.ast-main-header-wrap .ast-header-social-wrap svg {
transition: fill 0.3s ease-in-out;
fill: white; /* Default white color */
}
.ast-main-header-wrap.is-sticky .ast-header-social-1-wrap svg,
.ast-main-header-wrap.is-sticky .ast-header-social-wrap svg {
fill: #333333 !important; /* Dark color when sticky */
}
/* DROPDOWN MENU STYLES - CONSISTENT FOR BOTH DEFAULT AND STICKY STATES */
.main-header-menu .sub-menu,
.ast-builder-menu-element .sub-menu,
.ast-main-header-wrap.is-sticky .main-header-menu .sub-menu,
.ast-main-header-wrap.is-sticky .ast-builder-menu-element .sub-menu {
background-color: rgba(255, 255, 255, 0.95) !important;
backdrop-filter: blur(5px);
min-width: 200px;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
/* Dropdown menu items - consistent styling */
.main-header-menu .sub-menu li,
.ast-builder-menu-element .sub-menu li,
.ast-main-header-wrap.is-sticky .main-header-menu .sub-menu li,
.ast-main-header-wrap.is-sticky .ast-builder-menu-element .sub-menu li {
background-color: transparent;
}
/* Dropdown menu links - consistent styling */
.main-header-menu .sub-menu a,
.ast-builder-menu-element .sub-menu a,
.ast-main-header-wrap.is-sticky .main-header-menu .sub-menu a,
.ast-main-header-wrap.is-sticky .ast-builder-menu-element .sub-menu a {
color: #333333 !important;
padding: 15px 20px;
display: block;
text-decoration: none;
font-weight: 400;
}
.main-header-menu .sub-menu a:hover,
.ast-builder-menu-element .sub-menu a:hover,
.ast-main-header-wrap.is-sticky .main-header-menu .sub-menu a:hover,
.ast-main-header-wrap.is-sticky .ast-builder-menu-element .sub-menu a:hover {
background-color: rgba(0, 124, 186, 0.1) !important;
color: #007cba !important;
}
.main-header-menu li:hover .sub-menu,
.ast-builder-menu-element li:hover .sub-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
TASK: Add functions to the functions.php file
Steps to Implement:
-
Create PHP File:
- Navigate to:
wp-content/themes/astra-child/ - Create a new file named:
functions.php
- Navigate to:
-
Add PHP Code:
- Open
functions.phpand paste the following code and save the file:
- Open
<?php
/**
* Astra Child Theme functions and definitions
*
* This file is where you'll add custom functions for your child theme.
* It's crucial not to modify the parent theme's files directly, as your
* changes would be lost during theme updates.
*/
/**
* Enqueue child theme styles and custom scripts.
*
* Note: Astra automatically handles parent theme stylesheets through its
* sophisticated enqueue system. We only need to enqueue our custom assets.
*/
function astra_child_enqueue_styles() {
// Get theme version for cache busting
$theme_version = wp_get_theme()->get('Version');
// Enqueue custom JavaScript for the sticky header
// Loaded in footer for better performance
wp_enqueue_script(
'astra-child-sticky-header',
get_stylesheet_directory_uri() . '/custom-sticky.js',
array(), // No dependencies needed for vanilla JS
$theme_version,
true // Load in footer
);
}
// Hook the enqueue function to the 'wp_enqueue_scripts' action
add_action( 'wp_enqueue_scripts', 'astra_child_enqueue_styles' );
-
Verify the File Is Active:
- Go to WordPress Dashboard > Appearance > Theme File Editor.
- Select the Astra Child theme.
- Confirm
functions.phpis listed.
Limitations
I was unable to update the functions.php file directly from the WordPress admin dashboard.
Workaround
As a workaround, I manually edited the functions.php file located in the wp-content/themes/astra-child/ directory.
TASK: Change the color of social links and site logo on scrolling
Added the additional css to https://github.com/fossasia/codeheat.org/issues/368#issuecomment-3095935079
starting with comments /* Logo color change on sticky */
Screencast of Sticky Headers
https://github.com/user-attachments/assets/d91c2cdb-ffb0-4778-afcf-65eaa08c2459
ISSUE: Change color of drop down menu
Change color of the drop-down menu from transparent to white similar to original website
TASK: Change color of drop down menu
Added the additional css to https://github.com/fossasia/codeheat.org/issues/368#issuecomment-3095935079
starting with comments /* DROPDOWN MENU STYLES - CONSISTENT FOR BOTH DEFAULT AND STICKY STATES */
https://github.com/user-attachments/assets/2a37bbe6-0976-45af-bc88-7a74aeb92e90
Screencast of drop down menu
Final Iteration
/* HEADER DEFAULT STATE - FIXED TO TOP FOR INITIAL APPEARANCE AND SMOOTH TRANSITION */
.ast-main-header-wrap {
/* Merged Properties: Fixed position takes precedence */
position: fixed; /* Ensures header is always at the top and covers the full width */
top: 0;
width: 100%;
z-index: 999; /* Higher z-index ensures it's above other elements */
/* Existing properties for smooth transition and default look */
transition: all 0.3s ease-in-out;
background-color: transparent;
}
/* Use transform for smoother animations - This class is added on scroll by JavaScript */
.ast-main-header-wrap.is-sticky {
/* 'position: fixed;' is now redundant here but kept for clarity/safety */
position: fixed;
width: 100%;
background-color: rgba(255, 255, 255, 0.9);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
backdrop-filter: blur(5px); /* Optional: for frosted glass effect */
transform: translateZ(0); /* Hardware acceleration */
}
/* Prevent layout shift by reserving space */
body {
/* You'll need to use JavaScript to add padding-top to the body
equal to the header's height when the 'is-sticky' class is *not* present,
or simply rely on the 'position: fixed' always being active.
If 'position: fixed' is ALWAYS on, the body padding is only needed to push
the *content* down, not to prevent a 'shift'. */
padding-top: 0;
transition: padding-top 0.3s ease-in-out;
}
/* Text color transitions */
.ast-main-header-wrap .main-header-menu a,
.ast-main-header-wrap .ast-builder-menu-element a,
.ast-main-header-wrap .ast-social-stack a,
.ast-main-header-wrap .ast-social-stack svg,
.ast-main-header-wrap .ast-social-stack i,
.ast-main-header-wrap .site-title a,
.ast-main-header-wrap .site-description {
transition: color 0.3s ease-in-out;
}
.ast-main-header-wrap.is-sticky .main-header-menu a,
.ast-main-header-wrap.is-sticky .ast-builder-menu-element a,
.ast-main-header-wrap.is-sticky .ast-social-stack a,
.ast-main-header-wrap.is-sticky .ast-social-stack svg,
.ast-main-header-wrap.is-sticky .ast-social-stack i,
.ast-main-header-wrap.is-sticky .site-title a,
.ast-main-header-wrap.is-sticky .site-description {
color: #333333 !important;
}
/* Logo color change on sticky */
.ast-main-header-wrap .site-logo-img img,
.ast-main-header-wrap .custom-logo {
transition: filter 0.3s ease-in-out;
}
.ast-main-header-wrap.is-sticky .site-logo-img img,
.ast-main-header-wrap.is-sticky .custom-logo {
filter: brightness(0) saturate(100%) invert(20%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(20%) contrast(100%);
}
/* Social icons color change on sticky */
.ast-main-header-wrap .ast-header-social-1-wrap svg,
.ast-main-header-wrap .ast-header-social-wrap svg {
transition: fill 0.3s ease-in-out;
fill: white; /* Default white color */
}
.ast-main-header-wrap.is-sticky .ast-header-social-1-wrap svg,
.ast-main-header-wrap.is-sticky .ast-header-social-wrap svg {
fill: #333333 !important; /* Dark color when sticky */
}
/* DROPDOWN MENU STYLES - CONSISTENT FOR BOTH DEFAULT AND STICKY STATES */
.main-header-menu .sub-menu,
.ast-builder-menu-element .sub-menu,
.ast-main-header-wrap.is-sticky .main-header-menu .sub-menu,
.ast-main-header-wrap.is-sticky .ast-builder-menu-element .sub-menu {
background-color: rgba(255, 255, 255, 0.95) !important;
backdrop-filter: blur(5px);
min-width: 200px;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
/* Dropdown menu items - consistent styling */
.main-header-menu .sub-menu li,
.ast-builder-menu-element .sub-menu li,
.ast-main-header-wrap.is-sticky .main-header-menu .sub-menu li,
.ast-main-header-wrap.is-sticky .ast-builder-menu-element .sub-menu li {
background-color: transparent;
}
/* Dropdown menu links - consistent styling */
.main-header-menu .sub-menu a,
.ast-builder-menu-element .sub-menu a,
.ast-main-header-wrap.is-sticky .main-header-menu .sub-menu a,
.ast-main-header-wrap.is-sticky .ast-builder-menu-element .sub-menu a {
color: #333333 !important;
padding: 8px 20px;
display: block;
text-decoration: none;
font-weight: 400;
}
/* Force dropdown padding for normal AND sticky states */
.main-header-menu .sub-menu a,
.ast-builder-menu-element .sub-menu a {
padding: 8px 20px !important;
}
.main-header-menu .sub-menu a:hover,
.ast-builder-menu-element .sub-menu a:hover,
.ast-main-header-wrap.is-sticky .main-header-menu .sub-menu a:hover,
.ast-main-header-wrap.is-sticky .ast-builder-menu-element .sub-menu a:hover {
background-color: rgba(0, 124, 186, 0.1) !important;
color: #007cba !important;
}
.main-header-menu li:hover .sub-menu,
.ast-builder-menu-element li:hover .sub-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}