Skip to content

janzheng/svelte-masonry

Repository files navigation

svelte-masonry

A lightweight Masonry implementation for Svelte, based on Ana Tudor's CSS-Tricks article. No external dependencies required.

Demo

Both demos can be found under /src/routes/

This is an implementation of Masonry based on this excellent article by Ana Tudor (@anatudor) on CSS Tricks: https://css-tricks.com/a-lightweight-masonry-solution. It's really great. It requires no external dependencies, is super light-weight, etc.

Basically I just wrapped Svelte around the Masonry code as a reusable component.

Installation

npm install svelte-masonry

or

yarn add svelte-masonry

Basic Usage

<script>
  import Masonry from 'svelte-masonry';
  
  let data = [
    { name: 'Item 1', text: 'Some content...' },
    { name: 'Item 2', text: 'More content...' }
  ];
</script>

<Masonry 
  stretchFirst={true} 
  gridGap={'0.75rem'} 
  colWidth={'minmax(Min(20em, 100%), 1fr)'}
>
  {#each data as item}
    <div class="card">
      <h3>{item.name}</h3>
      <p>{item.text}</p>
    </div>
  {/each}
</Masonry>

Component Props

  • stretchFirst (boolean): Stretches the first item across the full width
  • gridGap (string): Space between grid items (default: '0.5em')
  • padding (string): Padding around the entire grid (default: '0px')
  • colWidth (string): Column width using CSS grid values (default: 'minmax(Min(20em, 100%), 1fr)')
  • items (array): Optional array of data items - pass this if your grid content updates dynamically
  • reset (boolean): Trigger to force grid recalculation

Working with Dynamic Content

Images and Async Content

When working with images or other async content, use the refreshLayout binding:

An example can be found under /src/routes/pics/+page.svelte

<script>
  import Masonry from 'svelte-masonry';
  import { onMount } from 'svelte';

  let refreshLayout;
  let images = [];
  
  onMount(async () => {
    images = await fetchImages();
  });
</script>

<Masonry 
  items={images}
  bind:refreshLayout={refreshLayout}
  gridGap={'0.75rem'}
>
  {#each images as image}
    <img 
      src={image.url} 
      alt={image.alt}
      on:load={refreshLayout}
      class="w-full h-auto"
    />
  {/each}
</Masonry>

Dynamic Updates (e.g., "Load More")

<script>
  import Masonry from 'svelte-masonry';
  let items = [];
  let refreshLayout;
  
  async function loadMore() {
    const newItems = await fetchMoreItems();
    items = [...items, ...newItems];
  }
</script>

<button on:click={loadMore}>Load More</button>

<Masonry 
  items={items}
  bind:refreshLayout={refreshLayout}
  gridGap={'0.75rem'}
>
  {#each items as item}
    <div class="card">
      <h3>{item.name}</h3>
      <p>{item.text}</p>
    </div>
  {/each}
</Masonry>

Important Implementation Notes

  1. Async Content Loading

    • Always bind refreshLayout when working with async content
    • Trigger refreshLayout on image load events
    • Pass the items prop when content updates dynamically
  2. Layout Updates The layout automatically refreshes when:

    • Window is resized
    • Items array changes
    • reset prop is triggered
    • refreshLayout() is manually called
  3. Grid Behavior

    • Uses CSS Grid under the hood
    • Automatically adjusts columns based on viewport width
    • Can stretch first item full-width with stretchFirst
    • Centers content with justify-content: center

Development

You're welcome to create an issue, feature request, or a pull request and I'll take a look, but this won't be a very managed repo. Instead, please read the the CSS tricks article, check out the source code, or ask the author (@anatudor) directly about the implementation (this repo is not related to the author, but an implementation of the CSS tricks article).

License

The code was lifted from Ana Tudor (@anatudor) from CSS tricks. They have a funny license page, so you should take a look (https://css-tricks.com/license/). Do whatever you'd like with this example!

Deployment / Packaging

This project was built with Sveltekit Package https://svelte.dev/docs/kit/packaging / https://www.npmjs.com/package/@sveltejs/package.

To build the package, run npm run package. This will build the package and create a dist folder with the built files.

To publish the package, run npm publish. This will publish the package to the npm registry.

About

Masonry for Svelte

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published