Rotate the Logo on Scroll in WordPress

A round logo that turns as you scroll is a small detail that makes a WordPress site feel alive. Matthias Altmann used it on his site and shared the idea. This snippet rotates the logo on scroll: the further down the page, the more it turns, and scrolling back up turns it back.

It is plain JavaScript, so it works with block themes, which do not load jQuery on the front end, and it stays off for visitors who asked their system for reduced motion.

The snippet

(function () {
	// ===== Config =====
	var SELECTOR = '.wp-block-site-logo img'; // The logo to rotate.
	var SPEED = 0.5; // Degrees per pixel scrolled.
	// ===== End of config =====

	var logos = document.querySelectorAll(SELECTOR);
	if (!logos.length || window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
		return;
	}

	var ticking = false;

	function rotate() {
		ticking = false;
		var deg = window.scrollY * SPEED;
		logos.forEach(function (logo) {
			logo.style.transform = 'rotate(' + deg + 'deg)';
		});
	}

	window.addEventListener('scroll', function () {
		if (!ticking) {
			ticking = true;
			window.requestAnimationFrame(rotate);
		}
	}, { passive: true });

	rotate(); // Right angle when the page loads already scrolled.
})();

By default it rotates the image in the core Site Logo block. For a logo from a page builder or a custom header, change SELECTOR to its class or ID.

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 set Template to All, or narrow it to the pages that need the script. Under Script location tick Footer, set Footer Mode to Javascript, paste the code into the footer editor and publish.

Scripts Organizer prints header and footer code on the front end only with the Conditions trigger, not with Everywhere, and it adds the <script> tag itself, so paste the code without one.

How it works

  • On every scroll the angle is window.scrollY * SPEED, so 0.5 means one full turn per 720 pixels scrolled.
  • Scroll events fire faster than the screen repaints. The ticking flag and requestAnimationFrame() update the logo at most once per frame.
  • The listener is passive, which tells the browser it never blocks scrolling.
  • rotate() also runs once on load, so a page opened halfway down (after a reload or an anchor link) shows the right angle at once.
  • When the visitor has reduce motion turned on in their system settings, the script does nothing.

Customise it

  • Faster or slower: change SPEED. Use a negative value to turn the other way.
  • Smoother: add .wp-block-site-logo img { transition: transform 0.2s linear; } in a Header code block with Header Mode CSS.
  • Other effects: see Animate header logo on scroll for shrinking the logo instead.

Gotchas

  • Rotation turns the whole image, including its corners. Square logos with a background look odd; use a round or transparent logo.
  • If the logo is a link with a focus outline, the outline rotates too.

In the Scripts Organizer library Import it with one click from Scripts Organizer.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You’ll also get DPlugins product updates. No spam, and you can unsubscribe anytime.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You'll also get DPlugins product updates. No spam, and you can unsubscribe anytime.