https://github.com/janosh/svelte-bricks
Naive Svelte Masonry component without column balancing (ragged columns at the bottom)
https://github.com/janosh/svelte-bricks
layout masonry pinterest-layout svelte svelte-kit typescript
Last synced: 5 months ago
JSON representation
Naive Svelte Masonry component without column balancing (ragged columns at the bottom)
- Host: GitHub
- URL: https://github.com/janosh/svelte-bricks
- Owner: janosh
- License: mit
- Created: 2020-10-18T09:24:41.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2024-10-07T16:34:20.000Z (over 1 year ago)
- Last Synced: 2024-10-12T15:56:52.907Z (over 1 year ago)
- Topics: layout, masonry, pinterest-layout, svelte, svelte-kit, typescript
- Language: Svelte
- Homepage: https://janosh.github.io/svelte-bricks
- Size: 293 KB
- Stars: 105
- Watchers: 3
- Forks: 4
- Open Issues: 4
-
Metadata Files:
- Readme: readme.md
- Changelog: changelog.md
- License: license
Awesome Lists containing this project
README
## Installation
```sh
pnpm add -D svelte-bricks
```
## Usage
The kitchen sink for this component looks something like this:
```svelte
import Masonry from 'svelte-bricks'
let nItems = $state(30);
let items = $derived([...Array(nItems).keys()])
let [minColWidth, maxColWidth, gap] = [200, 800, 20]
let width = $state(0), height = $state(0)
Masonry size: {width}px × {height}px (w × h)
{#snippet children({ item })}
{/snippet}
```
**Note**: If `items` is an array of objects, this component tries to access an `id` property on each item. This value is used to tell items apart in the keyed `{#each}` block that creates the masonry layout. Without it, Svelte could not avoid duplicates when new items are added or existing ones rearranged. Read the [Svelte docs](https://svelte.dev/docs/svelte/each#Keyed-each-blocks) for details. To change the name of the identifier key, pass `idKey="some-uniq-key`. Or pass a function `getId = (item: Item) => string | number` that maps items to unique IDs.
## Props
`Masonry.svelte` expects an array of `items` as well as a `` component used to render each of the `items`. The array can contain whatever data (objects, strings, numbers) as long as the slot component knows how to handle it.
Additional optional props are:
1. ```ts
animate: boolean = true
```
Whether to [FLIP-animate](https://svelte.dev/docs/svelte/svelte-animate) masonry items when viewport resizing or other events cause `items` to rearrange.
1. ```ts
balance: boolean = true
```
Enable height-based column balancing. Items are distributed to the shortest column for a more even layout. Set to `false` for simple round-robin distribution.
1. ```ts
calcCols = (
masonryWidth: number,
minColWidth: number,
gap: number,
): number => {
return Math.min(
items.length,
Math.floor((masonryWidth + gap) / (minColWidth + gap)) || 1,
)
}
```
Function used to compute the number of columns based on the masonry width, minimum column width and gap.
1. ```ts
class: string = ``
```
Applies to the outer `div` wrapping all masonry columns. For use with CSS frameworks like Tailwind.
1. ```ts
columnClass: string = ``
```
Applies to each column `div`.
1. ```ts
duration: number = 200
```
Transition duration in milli seconds when masonry items are rearranged or added/removed. Set to 0 to disable transitions.
1. ```ts
gap: number = 20
```
Gap between columns and items within each column in `px`.
1. ```ts
getId = (item: Item): string | number => {
if (typeof item === `number`) return item
if (typeof item === `string`) return item
return item[idKey]
}
```
Custom function that maps masonry items to unique IDs of type `string` or `number`.
1. ```ts
idKey: string = `id`
```
Name of the attribute to use as identifier if items are objects.
1. ```ts
items: Item[]
```
The only required prop is the list of items to render where `Item` is a generic type (via `generics="Item"`) which usually will be `object` but can also be simple types `string` or `number`.
1. ```ts
masonryHeight: number = 0
```
The masonry `div`s height in `px`.
1. ```ts
masonryWidth: number = 0
```
The masonry `div`s width in `px`.
1. ```ts
maxColWidth: number = 500
```
Maximum column width in `px`.
1. ```ts
minColWidth: number = 330
```
Minimum column width in `px`.
1. ```ts
style: string = ``
```
Inline styles that will be applied to the top-level `div.masonry`.
## Virtual Scrolling
For large lists (1000+ items), enable virtual scrolling to render only visible items:
```svelte
item.height ?? 150}
overscan={5}
>
{#snippet children({ item })}
{/snippet}
```
### Virtualization Props
1. ```ts
virtualize: boolean = false
```
Enable virtual scrolling. When `true`, only visible items are rendered. Requires the `height` prop.
1. ```ts
height: number | string
```
Required when `virtualize=true`. Sets the scroll container height (e.g., `500` for pixels or `"80vh"`).
1. ```ts
getEstimatedHeight?: (item: Item) => number
```
Optional function that returns an estimated height for items before they're measured. Defaults to 150px if not provided. Better estimates = less layout shift.
1. ```ts
overscan: number = 5
```
Number of items to render above and below the visible area. Higher values reduce flicker during fast scrolling but render more items.
**Notes:**
- FLIP animations are automatically disabled when virtualizing
- Balance mode works with estimated heights until items are measured
- The masonry div becomes a scroll container (`overflow-y: auto`)
## Styling
Besides inline CSS which you can apply through the `style` prop, the following `:global()` CSS selectors can be used for fine-grained control of wrapper and column styles:
```css
:global(div.masonry) {
/* top-level wrapper div */
}
:global(div.masonry div.col) {
/* each column in the masonry layout */
}
```