Skip to content

Instantly share code, notes, and snippets.

@tak-dcxi
Last active July 15, 2024 17:34
Show Gist options
  • Save tak-dcxi/f05c050c273abf9e50e8fc39d1c16327 to your computer and use it in GitHub Desktop.
Save tak-dcxi/f05c050c273abf9e50e8fc39d1c16327 to your computer and use it in GitHub Desktop.
Masonry Layout
const resizeMasonryItem = (
element: HTMLElement,
itemWrapper: HTMLElement
): void => {
const item = itemWrapper.firstChild;
if (!(item instanceof HTMLElement)) return;
const rowSize = parseInt(getComputedStyle(element).gridAutoRows, 10);
const gapSize = parseInt(getComputedStyle(element).rowGap, 10);
const itemSize = isWritingModeVertical(element)
? item.getBoundingClientRect().width
: item.getBoundingClientRect().height;
const rowSpan = Math.ceil((itemSize + gapSize) / (rowSize + gapSize));
itemWrapper.style.setProperty("--_row-end", `span ${rowSpan}`);
};
const initializeMasonry = (element: HTMLElement): void => {
if (!element) return;
const items = [...element.children];
if (items.length === 0) return;
const resizeObserver = new ResizeObserver((entries) => {
entries.forEach((entry) => {
requestAnimationFrame(() => {
const target = entry.target;
if (target instanceof HTMLDivElement) {
resizeMasonryItem(element, target);
}
});
});
});
items.forEach((item) => {
const itemWrapper = document.createElement("div");
element.insertBefore(itemWrapper, item);
itemWrapper.appendChild(item);
resizeObserver.observe(itemWrapper);
});
};
const isWritingModeVertical = (element: HTMLElement): boolean => {
const { writingMode } = getComputedStyle(element);
return writingMode.includes("vertical") || writingMode.includes("sideways");
};
document.addEventListener("DOMContentLoaded", () => {
const target = document.querySelector(".masonry");
if (target instanceof HTMLElement) {
initializeMasonry(target);
}
});
:root {
--rem-ratio: calc(1rem / 16);
}
.masonry {
--_column-min-size: calc(320 * var(--rem-ratio));
--_gutter: 16px;
--_rows: 0;
contain: content;
display: block grid;
grid-template-columns: repeat(
auto-fill,
minmax(min(var(--_column-min-size), 100%), 1fr)
);
grid-auto-rows: var(--_rows);
gap: var(--_gutter);
@media (scripting: none) {
--_rows: unset;
}
}
.masonry > * {
grid-row-end: var(--_row-end);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment