@svelte-put/resize
GithubSvelte action wrapper for ResizeObserver
Compatible with or powered directly bySvelte runes.
Still on Svelte 4? Seethe old docs site here.
Prior Arts
- svelte-actions-resize: very minimal, no typescript support
- svelte-observer-resize: very similar to this implementation, but no typescript & ssr support
- svelte-resize-observer: component-based-strategy, includingresize-observer-polyfill by default
Installation
npm install --save-dev @svelte-put/resizepnpm add -D @svelte-put/resizeyarn add -D @svelte-put/resizeNew to Svelte 5? SeeMigration Guides.
Quick Start
Use theresizedCustomEvent (named so to avoid conflict with window'sresize event) as the callback forResizeObserver
<script lang="ts"> import {resize,type ResizeDetail }from '@svelte-put/resize'; function onResized(e: CustomEvent<ResizeDetail>) { const { observer,// see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver entry,// see https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry }= e.detail; }</script><div use:resize onresized={onResized} />Example
This example is ported fromMDN Docs, whereborder-radius will scale in proportion to the size of the box.
Expand the code block below to see how the example is implemented.
<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="bg-blue-500 px-2 text-white">blue</span> box (dragging bottom right corner) tosee change</p><divclass="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><inputtype="checkbox"id="resize-enable"bind:checked={enabled}class="c-input accent-primary h-5 w-5"/></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 thatResizeObserver 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, considerresize-observer-polyfill.
Migration Guides
V3 -> V4 (Svelte 5 in Runes mode)
When migrating to V4, you will need to change event directiveon:resized to standard attributeonresized:
<div use:resize on:resized></div><div use:resize onresized></div>Happy resizing! 👨💻