Created
June 16, 2026 04:47
-
-
Save ebucario/8763a188744839bcec78cce304b82fcf to your computer and use it in GitHub Desktop.
main-page-parallax-bg
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
| class MainPageParallaxBg extends HTMLElement { | |
| static observedAttributes = ["image-bg", "image-mid", "image-fg"]; | |
| divRefs = { | |
| "image-bg": null, | |
| "image-mid": null, | |
| "image-fg": null, | |
| }; | |
| attributeRefs = { | |
| "image-bg": null, | |
| "image-mid": null, | |
| "image-fg": null, | |
| }; | |
| connectedCallback() { | |
| const shadow = this.attachShadow({ mode: "open" }); | |
| const style = document.createElement("style"); | |
| style.innerText = ` | |
| #wrapper { | |
| width: 100%; | |
| height: 100%; | |
| position: relative; | |
| background: #004944; | |
| overflow: hidden; | |
| transition: transform-origin 2s ease-out; | |
| } | |
| .bg, | |
| .mid, | |
| .fg, | |
| .cover { | |
| display: block; | |
| position: absolute; | |
| background: right 40% center / cover; | |
| inset: 0; | |
| transform-origin: inherit; /* set in JS on mouseover of parent element */ | |
| } | |
| .bg { | |
| inset: -2.5vw; /* eyeballed a bit */ | |
| transform: scale(0.98); | |
| } | |
| .mid { | |
| transform: scale(1.05); | |
| filter: blur(2px); | |
| } | |
| .fg { | |
| transform: scale(1.2); | |
| filter: blur(5px); | |
| } | |
| .cover { | |
| /* 0.7 opacity before | |
| so it's 30% | |
| which is 0.3 * 256 | |
| which is 76.8 | |
| which in hex is 4c */ | |
| background-color: #ffffff4c; | |
| } | |
| `; | |
| shadow.appendChild(style); | |
| const div = document.createElement("div"); | |
| div.id = "wrapper"; | |
| const bg = document.createElement("div"); | |
| bg.classList.add("bg"); | |
| const mid = document.createElement("div"); | |
| mid.classList.add("mid"); | |
| const fg = document.createElement("div"); | |
| fg.classList.add("fg"); | |
| const cover = document.createElement("div"); | |
| fg.classList.add("cover"); | |
| this.divRefs["image-bg"] = bg; | |
| this.divRefs["image-mid"] = mid; | |
| this.divRefs["image-fg"] = fg; | |
| this.applyInlineStyles(); | |
| div.appendChild(bg); | |
| div.appendChild(mid); | |
| div.appendChild(fg); | |
| div.appendChild(cover); | |
| const mouseMove = (() => { | |
| let throttler = 0; | |
| return (e) => { | |
| if (throttler !== 0) return; | |
| throttler = setTimeout(() => { | |
| throttler = 0; | |
| }, 100); | |
| const leader = e.currentTarget; | |
| const rect = leader.getBoundingClientRect(); | |
| const width = ((e.clientX - rect.left) / rect.width) * 100; | |
| const height = ((e.clientY - rect.top) / rect.height) * 100; | |
| leader.style.transformOrigin = `${width.toFixed(2)}% ${height.toFixed(2)}%`; | |
| }; | |
| })(); | |
| div.onmousemove = window.matchMedia( | |
| "(prefers-reduced-motion: no-preference)", | |
| ).matches | |
| ? mouseMove | |
| : undefined; | |
| shadow.appendChild(div); | |
| } | |
| applyInlineStyles() { | |
| for (const ref of MainPageParallaxBg.observedAttributes) { | |
| const attribute = this.attributeRefs[ref]; | |
| const div = this.divRefs[ref]; | |
| console.log(`attribute: ${attribute}, div: ${div}`); | |
| if (attribute && div) { | |
| div.style.backgroundImage = `url(${attribute})`; | |
| } | |
| } | |
| } | |
| attributeChangedCallback(name, oldValue, newValue) { | |
| this.attributeRefs[name] = newValue; | |
| this.applyInlineStyles(); | |
| } | |
| } | |
| customElements.define("main-page-parallax-bg", MainPageParallaxBg); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment