Last active
April 28, 2024 12:57
-
-
Save tak-dcxi/544e26b4c198254745ef257d0b5d0f61 to your computer and use it in GitHub Desktop.
initializeAnchorPositioning
This file contains 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
const initializeAnchorPositioning = (): void => { | |
const anchorElements = document.querySelectorAll('[data-anchor]') as NodeListOf<HTMLElement> | |
anchorElements.forEach((anchorElement) => { | |
const targetId = anchorElement.getAttribute('data-anchor') | |
if (!targetId) return | |
const anchorTarget = document.getElementById(targetId) as HTMLElement | |
if (!anchorTarget) return | |
const debouncedSetCustomProperties = debounce(() => setCustomProperties(anchorElement, anchorTarget)) | |
window.addEventListener('resize', debouncedSetCustomProperties) | |
setCustomProperties(anchorElement, anchorTarget) | |
}) | |
} | |
const debounce = <T extends any[], R>(callback: (...args: T) => R): ((...args: T) => void) => { | |
let timeout: number | undefined | |
return (...args: T): void => { | |
if (timeout !== undefined) { | |
cancelAnimationFrame(timeout) | |
} | |
timeout = requestAnimationFrame(() => callback.apply(this, args)) | |
} | |
} | |
const isVerticalWritingMode = (element: HTMLElement): boolean => { | |
const writingMode = window.getComputedStyle(element).writingMode | |
return writingMode.includes('vertical') || writingMode.includes('sideways') | |
} | |
const setCustomProperties = (anchorElement: HTMLElement, targetElement: HTMLElement): void => { | |
const rect = targetElement.getBoundingClientRect() | |
const isVertical = isVerticalWritingMode(targetElement) | |
const anchorStyles = { | |
'--anchor-inline-start': isVertical ? `${rect.top}px` : `${rect.left}px`, | |
'--anchor-inline-end': isVertical ? `${rect.bottom}px` : `${rect.right}px`, | |
'--anchor-block-start': isVertical ? `${rect.left}px` : `${rect.top}px`, | |
'--anchor-block-end': isVertical ? `${rect.right}px` : `${rect.bottom}px`, | |
'--anchor-inline-center': `calc(var(--anchor-inline-start) + ${isVertical ? rect.height : rect.width}px / 2)`, | |
'--anchor-block-center': `calc(var(--anchor-block-start) + ${isVertical ? rect.width : rect.height}px / 2)`, | |
'--anchor-inline-translate': isVertical ? '-50%' : '0 -50%', | |
'--anchor-block-translate': isVertical ? '0 -50%' : '-50%', | |
} | |
for (const [property, value] of Object.entries(anchorStyles)) { | |
anchorElement.style.setProperty(property, value) | |
} | |
} | |
export default initializeAnchorPositioning |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment