@svelte-put/resize GitHub Github

Svelte action wrapper for ResizeObserver

@svelte-put/resize @svelte-put/resize @svelte-put/resize @svelte-put/resize

Still on Svelte 4? See the old docs site here.

Prior Art

Installation

npm install --save-dev @svelte-put/resize
pnpm add -D @svelte-put/resize
yarn add -D @svelte-put/resize

New to Svelte 5? See Migration Guides.

Quick Start

Use the resized CustomEvent (named so to avoid conflict with window's resize event) as the callback for ResizeObserver

<script>
  import { resize } from '@svelte-put/resize';
</script>

<div use:resize on:resized />

Example

This example is ported from MDN Docs, where border-radius will scale in proportion to the size of the box.

Example

Resize blue box (dragging bottom right corner) to see change

<script lang="ts">
  import { resize } from '@svelte-put/resize';
  import type { ResizeDetail } from '@svelte-put/resize';

  let enabled = $state(true);

  function calcBorderRadius(size1: number, size2: number) {
    return `${Math.min(100, size1 / 10 + size2 / 10)}px`;
  }

  function onResized(e: CustomEvent<ResizeDetail>) {
    const { entry } = e.detail;

    const target = entry.target as HTMLElement;
    if (entry.borderBoxSize?.length > 0) {
      target.style.borderRadius = calcBorderRadius(
        entry.borderBoxSize[0].inlineSize,
        entry.borderBoxSize[0].blockSize,
      );
    } else {
      target.style.borderRadius = calcBorderRadius(
        entry.contentRect.width,
        entry.contentRect.height,
      );
    }
  }

  let box: HTMLDivElement;
	$effect(() => {
		if (!enabled) box.style.borderRadius = '8px';
	})
</script>

<div class="flex flex-col items-center space-y-4">
  <p>Resize <span class="px-2 bg-blue-500 text-white">blue</span> box (dragging bottom right corner) to see change</p>
  <div
    class="h-24 w-24 resize overflow-auto bg-blue-500"
    use:resize={{ enabled }}
    onresized={onResized}
    bind:this={box}
  ></div>
  <div class="flex items-center space-x-2">
    <label for="resize-enable">Check to {enabled ? 'disable' : 'enable'} action:</label>
    <input
      type="checkbox"
      id="resize-enable"
      bind:checked={enabled}
      class="c-input h-5 w-5 accent-primary"
    />
  </div>
</div>

Configuration

resize accepts a config object with the following interface.

/** config behavior of `resize` */
export interface ResizeConfig {
	/**
	 * whether to activate the action. Default to `true`
	 * @default true
	 */
	enabled?: boolean;
	/**
	 * Be default, a singleton ResizeObserver is used for all actions for
	 * better performance. You can use this option to create a new ResizeObserver
	 * or provide your own.
	 * @default 'singleton'
	 */
	observer?: 'singleton' | 'new' | ResizeObserver;

	/**
	 * Options passed to {@link https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe#options | ResizeObserver.observe}
	 * @default undefined
	 */
	options?: ResizeObserverOptions;
}

Browser Support & Polyfill

As of this writing, caniuse shows that ResizeObserver is supported by all major browsers, but not IE11. @svelte-put/resize tries to stay minimal and hence does not include a polyfill. If one is needed, consider resize-observer-polyfill.

Migration Guides

V3 -> V4 (Svelte 5 in Runes mode)

When migrating to V4, you will need to change event directive on:resized to standard attribute onresized:

<div use:resize on:resized></div>
<div use:resize onresized></div>

Happy resizing! 👨‍💻

Edit this page on Github