---
title: "ResizeBox"
description: "A container that animates between explicit width and height targets."
category: Primitives
status: beta
since: 0.3.9
tags: [resize, layout, animation]
syncStatus: reviewed
verified: true
---

## Usage

### Explicit Size Targets
The parent supplies `width` / `height` targets; `resize-start` / `resize-end` mark where each transition begins and ends.
:::TuffDemoWrapper{demo="ResizeBoxResizeBoxDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import { computed, ref } from 'vue'

  const expanded = ref(false)
  const width = computed(() => expanded.value ? 'min(420px, 100%)' : 'min(220px, 100%)')
  const height = computed(() => expanded.value ? 244 : 132)
  </script>

  <template>
    <TxButton @click="expanded = !expanded">Toggle</TxButton>

    <TxResizeBox
      as="section"
      :width="width"
      :height="height"
      :duration="360"
      :disabled="disabled"
      :clip="clip"
      @resize-start="status = 'resizing'"
      @resize-end="status = 'settled'"
    >
      Explicitly sized content
    </TxResizeBox>
  </template>
---
:::

### Best Practices

- Use `TxResizeBox` when the parent already knows the compact and expanded targets; for content-driven changes such as images, async rendering, or wrapping, use [`TxAutoSizer`](./auto-sizer.en.mdc).
- Set only the axes you own; an unset axis keeps its intrinsic size.
- Give responsive targets as CSS lengths such as `min(420px, 100%)` so narrow screens don't overflow.
- Keep `clip` on when content is larger than the compact target; turn it off only for intentional overflow.
- Treat `resize-start` / `resize-end` as lifecycle notifications; the props are the source of truth for size.

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `as` | `string` | `div` | Root element tag; forwarded attrs, `class`, and `style` land on the root. |
| `width` | `number \| string` | `undefined` | Width target: finite numbers become px, non-empty strings pass through as CSS lengths; unset keeps the intrinsic width. |
| `height` | `number \| string` | `undefined` | Height target, with the same rules as `width`. |
| `duration` | `number` | `300` | Width and height transition duration in ms. |
| `easing` | `string` | `cubic-bezier(0.22, 1, 0.36, 1)` | Timing function shared by both size transitions. |
| `disabled` | `boolean` | `false` | Removes the transition so new targets apply at once; disabling mid-resize ends the lifecycle. |
| `clip` | `boolean` | `true` | Applies `overflow: hidden` to the root. |

### Events

| Event | Payload | Description |
|-------|---------|-------------|
| `resize-start` | `()` | Fires when a size target changes with animation on; changes during a resize stay in the same lifecycle. |
| `resize-end` | `()` | Fires when the last width/height transition ends, the safety timer fires, or a resize is disabled. |

### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `default` | - | Content rendered directly in the root, without extra wrapping or measurement. |

### Exposed Methods

| Name | Type | Description |
|------|------|-------------|
| `rootEl` | `HTMLElement \| null` | The current root element. |
| `animating` | `boolean` | Whether a size transition lifecycle is active. |

## Overview

- Finite numbers become px; non-empty strings pass through, so `%`, `rem`, `calc()`, and `min()` work directly. `undefined`, `null`, non-finite numbers, and blank strings leave the axis unset.
- CSS lengths are not validated: negative and invalid values go to the browser as-is, and if no transition runs, the safety timer still ends the lifecycle.
- Only the root's own `width` / `height` transitions count; transition events from children or other properties are ignored.
- With `disabled`, target changes snap without events; under reduced motion the transition shortens to `0.01ms` and the lifecycle still ends.
- Changing only the slot content never starts a resize; there is no content measurement, `ResizeObserver`, or `v-model`.

## Technologies

- Size changes ride a CSS `transition` on the root; the lifecycle ends on `transitionend` or a duration-based safety timer.
- Source: `packages/tuffex/packages/components/src/resize-box/`.

<TuffDocSourceLink />
