A big logo looks good at the top of a WordPress page, but once the visitor scrolls, a tall sticky header eats the screen. This snippet shrinks the header logo on scroll: as soon as the page moves, the header gets the class header-alt and the logo animates to a smaller height. Scroll back to the top and it grows again.
It is plain JavaScript and CSS. No jQuery and no library.
The markup
Add the class header to your header and brand to the logo. In the block editor or Site Editor, use Advanced → Additional CSS class(es) on the header Group and on the Site Logo or Image block; the CSS then sizes the image inside that block. In hand-written markup, put brand on the <img>:
<header class="header">
<a href="/">
<img class="brand" src="/wp-content/uploads/logo.svg" alt="Site name" width="400" height="120">
</a>
</header>
The CSS
/* img.brand: a plain image; .brand img: a Site Logo or Image block with the class. */
.header img.brand,
.header .brand img {
display: block;
width: auto;
height: auto;
max-height: 120px;
transition: max-height 0.4s ease;
}
.header.header-alt img.brand,
.header.header-alt .brand img {
max-height: 50px;
}
@media (prefers-reduced-motion: reduce) {
.header img.brand,
.header .brand img {
transition: none;
}
}
The JavaScript
(function () {
var offset = 1; // Pixels scrolled before the header gets the class.
var headers = document.querySelectorAll('.header');
if (!headers.length) {
return;
}
var ticking = false;
function update() {
var scrolled = window.scrollY >= offset;
headers.forEach(function (header) {
header.classList.toggle('header-alt', scrolled);
});
ticking = false;
}
window.addEventListener('scroll', function () {
if (!ticking) {
ticking = true;
window.requestAnimationFrame(update);
}
}, { passive: true });
update();
})();
Add it with Scripts Organizer
In Scripts Organizer go to Code Blocks → Add New and give the block a name. Set Trigger location to Conditions and leave Template on All. Under Script location tick Header and Footer.
- Header: set Header Mode to CSS and paste the CSS.
- Footer: set Footer Mode to Javascript and paste the JavaScript.
Publish and enable the block. Scripts Organizer prints Header and Footer code on the front end only with the Conditions trigger, not with Everywhere.
How it works
- The script adds
header-altto every.headerwhenwindow.scrollYis at leastoffsetpixels, and removes it again near the top. - The scroll listener is passive and runs the class update at most once per frame with
requestAnimationFrame, so scrolling stays smooth. update()also runs once on load. A visitor who reloads halfway down the page gets the small logo right away.- The CSS animates
max-height, so the logo keeps its aspect ratio. With reduce motion turned on in the operating system, the logo switches size without animating. - The older version used
$(function () { … }). WordPress loads jQuery in noConflict mode, so$is undefined and the script stopped with an error.
Customise it
- Shrink later: set
var offset = 100;so the logo changes after 100px of scrolling. - Sizes and speed: change
120px,50pxand0.4sin the CSS. - Make the header itself sticky with
.header { position: sticky; top: 0; z-index: 10; }. With the admin bar, addtop: var(--wp-admin--admin-bar--height, 0px). - More effects on the same class: change the header background or padding under
.header.header-alt. For a header that hides on scroll down, see Show navigation on scroll up.
Gotchas
.headeris a common class name. If your theme already uses it for something else, rename it in the markup, the CSS and thequerySelectorAll()call.- An SVG logo without
widthandheightattributes can collapse to zero width withwidth: auto. Give the image its real dimensions. - Animating height moves the content under a non-sticky header. With a sticky header it does not.
In the Scripts Organizer library Import it with one click from Scripts Organizer.