Locking CSS3 transform-origin to scrollY inside a HubSpot CMS Custom Module (360° Easter Egg)

Hi everyone,

I’m building an interactive Easter egg custom module (module.html + module.css + module.js) for a HubSpot CMS landing page that rotates the page wrapper 360 degrees (and up to 20x) when a visitor double-taps Z or clicks a trigger button.

Inside a standard static HTML DOM, I solved the vertical scroll-swing bug by dynamically binding transform-origin to the user’s current viewport center before triggering the CSS transition (you can see the working vanilla CSS3/JS physics behavior on my test sandbox at https://doabarrelroll.co/ and the 20-turn stress test at Do a Barrel Roll 20 Times (20x) — 7,200° Spin Simulator):

JavaScript

const centerY = window.scrollY + (window.innerHeight / 2);
wrapper.style.transformOrigin = `50% ${centerY}px`;
wrapper.style.transition = 'transform 4s cubic-bezier(0.45, 0.05, 0.55, 0.95)';
wrapper.style.transform = 'rotate(360deg)';

However, when I wrap this inside a HubSpot CMS drag-and-drop DnD area (.dnd-section), HubSpot’s default .body-container-wrapper overflow rules clip the corners during the 90° and 270° rotation frames unless I target document.body directly.

For anyone who has built full-viewport CSS keyframe effects inside HubSpot CMS themes: is it better to attach the transform class to .body-container-wrapper via module.js, or inject a theme-level base.html wrapper div so HubSpot’s top preview bar stays stationary?