Skip to content

Instantly share code, notes, and snippets.

@tak-dcxi
Last active April 28, 2024 12:57
Show Gist options
  • Save tak-dcxi/544e26b4c198254745ef257d0b5d0f61 to your computer and use it in GitHub Desktop.
Save tak-dcxi/544e26b4c198254745ef257d0b5d0f61 to your computer and use it in GitHub Desktop.
initializeAnchorPositioning
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