Last active
October 9, 2023 03:50
-
-
Save ImKubass/2a1a5ae716f6adb7bb9b0cdae7fd9bd0 to your computer and use it in GitHub Desktop.
Same height of elements
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
export const sameHeight = (group: Element, elements: string | NodeListOf<HTMLElement>, byRow = false) => { | |
const targets = elements instanceof NodeList ? Array.from(elements) : Array.from(group.querySelectorAll<HTMLElement>(elements)) | |
const getHighestElement = (elements: HTMLElement[] = targets): number => { | |
const heights = elements.map((box) => box.clientHeight) | |
return Math.max(...heights) | |
} | |
const resetHeight = (elements: HTMLElement[] = targets) => { | |
elements.forEach((element) => element.style.removeProperty("height")) | |
} | |
const updateHeight = (elements: HTMLElement[] = targets) => { | |
const theHighest = `${getHighestElement(elements)}px` | |
elements.forEach((element) => element.style.setProperty("height", theHighest)) | |
} | |
const updateByRow = () => { | |
const rows = Array.from(new Set(targets.map((target) => target.offsetTop))) | |
const elementsCollection: HTMLElement[][] = [] | |
let targetsToFilter = targets | |
rows.forEach((row) => { | |
const elementsInSameRow = targets.filter((target) => target.offsetTop === row) | |
elementsCollection.push(elementsInSameRow) | |
targetsToFilter = targetsToFilter.filter((item) => !elementsInSameRow.includes(item)) | |
}) | |
elementsCollection.forEach((elements) => updateHeight(elements)) | |
} | |
const resizeObserver = new ResizeObserver(() => { | |
resetHeight() | |
byRow ? updateByRow() : updateHeight() | |
}) | |
resizeObserver.observe(group) | |
} | |
const init = () => { | |
const groups = document.querySelectorAll(`[data-same-height]`) | |
groups.forEach((group) => { | |
const byRow = group.hasAttribute("data-same-height-by-row") | |
const targets = Array.from(group.querySelectorAll<HTMLElement>(`[data-same-height-target]`)) | |
const collections = Array.from(new Set(targets.map((target) => target.getAttribute("data-same-height-target")))) | |
collections.forEach((collection) => { | |
const collectionElements = group.querySelectorAll<HTMLElement>(`[data-same-height-target="${collection}"]`) | |
sameHeight(group, collectionElements, byRow) | |
}) | |
}) | |
} | |
// call after rerender -> document.dispatchEvent(new Event("sameHeight")) -> reinitialize | |
document.addEventListener("sameHeight", () => init()) | |
init() |
HTML data atributes usage examples:
{# example 1 #}
<div class="group" data-same-height>
<article class="item">
<div class="item__header" data-same-height-target></div>
<div class="item__content"></div>
</article>
<article class="item">
<div class="item__header" data-same-height-target></div>
<div class="item__content"></div>
</article>
<article class="item">
<div class="item__header" data-same-height-target></div>
<div class="item__content"></div>
</article>
</div>
{# example 2 - for grid items, if items are not in one line #}
<div class="group" data-same-height data-same-height-by-row>
<article class="item">
<div class="item__header" data-same-height-target></div>
<div class="item__content"></div>
</article>
<article class="item">
<div class="item__header" data-same-height-target></div>
<div class="item__content"></div>
</article>
<article class="item">
<div class="item__header" data-same-height-target></div>
<div class="item__content"></div>
</article>
</div>
{# example 3 - Multiple targets collections #}
<div class="group" data-same-height>
<article class="item">
<div class="item__header" data-same-height-target="header"></div>
<div class="item__content" data-same-height-target="content"></div>
</article>
<article class="item">
<div class="item__header" data-same-height-target="header"></div>
<div class="item__content" data-same-height-target="content"></div>
</article>
<article class="item">
<div class="item__header" data-same-height-target="header"></div>
<div class="item__content" data-same-height-target="content"></div>
</article>
</div>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage example: