window-size
Track the window size reactively.
| Package | @vizejs/composable/window-size |
| Own the source | vize lib pull composable:window-size |
| Runtime exports | useWindowSize |
| Gzip budget | 1536 B |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/composable
Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.
import { useWindowSize } from "@vizejs/composable/window-size";
Try it
Lay out review cards using this viewport's real size
Read actual window dimensions and support without letting responsive changes overwrite the user's layout choice or draft.
What to observe: Resize the preview and compare the readonly width and height with its viewport. Automatic uses two columns from 640 CSS pixels; Single column keeps one at every width. Toggle Show layout measurements and edit the draft, then resize again: both choices remain. The measurement label always reports actual dimensions independently of the layout override.
useWindowSize() exposes readonly width, height, and isSupported refs. Default inner dimensions include scrollbars; includeScrollbar: false would use the document root's client dimensions, and type: outer would measure the outer browser window. This example uses the default real iframe window and no injected host. During SSR and the first hydrating render, dimensions are 0 by default and support is false; mounting attaches the actual window and reads its size. Resize and orientationchange then refresh it. initialWidth and initialHeight can supply a consistent application-chosen SSR fallback, not a detected browser size. The native select, checkbox, and draft own separate local state. Scope disposal removes passive listeners and the host watcher. The surrounding page and this iframe need not have the same dimensions.
Compare the initial and interacted states


Copy the example
Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.
<script setup lang="ts">
import { computed, ref } from "vue";
import { useWindowSize } from "@vizejs/composable/window-size";
const { width, height, isSupported } = useWindowSize();
const layout = ref<"automatic" | "single">("automatic");
const columns = computed(() => (layout.value === "automatic" && width.value >= 640 ? 2 : 1));
const showMeasurements = ref(false);
const draft = ref("");
</script>
<template>
<div class="composable-example">
<label>
Guide layout
<select v-model="layout">
<option value="automatic">Automatic</option>
<option value="single">Single column</option>
</select>
</label>
<div
class="viewport-guides"
:style="{ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` }"
>
<section aria-label="Compiler review card">
<strong>Compiler</strong>
<p>Inspect the generated render function.</p>
</section>
<section aria-label="Type check review card">
<strong>Type checking</strong>
<p>Review diagnostics against the same source.</p>
</section>
</div>
<label class="measurement-choice">
<input v-model="showMeasurements" type="checkbox" /> Show layout measurements
</label>
<p v-if="showMeasurements">
Layout: {{ columns }} {{ columns === 1 ? "column" : "columns" }} · Choice: {{ layout }}
</p>
<label>
Viewport review draft
<input v-model="draft" type="text" placeholder="Local draft survives a resize" />
</label>
<output aria-live="polite">
Viewport: {{ width }} × {{ height }} CSS pixels · Window support:
{{ isSupported ? "available" : "unavailable" }}
</output>
<p>
Resize this preview's viewport to update its readonly dimensions. Automatic uses two columns
from 640 px; Single column remains your choice at any width. Resizing preserves the local
draft and measurement visibility.
</p>
<p>
Default inner dimensions include scrollbars and describe this iframe, not the parent page or
the outer browser window. SSR starts at 0 × 0 with support unavailable; after mounting, the
real window supplies its dimensions.
</p>
</div>
</template>
<style scoped>
.viewport-guides {
display: grid;
gap: 12px;
& section {
min-inline-size: 0;
padding: 12px;
border: 1px solid currentColor;
border-radius: 8px;
}
}
.measurement-choice {
display: inline-flex;
align-items: center;
gap: 6px;
& input {
inline-size: auto;
}
}
</style>
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
useWindowSize |
dom | experimental | deterministic-fallback | stable | reactive-scope | web, desktop | window |
tryOnScopeDispose |
API
useWindowSize
Track the window size reactively. Server renders expose initialWidth/initialHeight (default 0), so the first client render matches; the real size is applied as soon as a window resolves (after mounting when called inside a component). Resize (and orientation) listeners are passive and removed with the owning reactive scope.
function useWindowSize(options: UseWindowSizeOptions = {}): WindowSizeControls
Types
WindowSizeHost
Window-like capability observed by useWindowSize.
| Member | Type | Description |
|---|---|---|
innerWidth |
number |
Viewport width including the vertical scrollbar. |
innerHeight |
number |
Viewport height including the horizontal scrollbar. |
outerWidth |
number |
Outer browser window width. |
outerHeight |
number |
Outer browser window height. |
document |
{ readonly documentElement: { readonly clientWidth: number; readonly clientHeight: number }; } |
Document whose root element reports the scrollbar-free viewport. |
UseWindowSizeOptions
Options for useWindowSize.
| Member | Type | Description |
|---|---|---|
initialWidth? |
number |
Width exposed during server rendering and before hydration. |
initialHeight? |
number |
Height exposed during server rendering and before hydration. |
includeScrollbar? |
boolean |
Include scrollbars in the inner dimensions. When false, the root element's clientWidth/clientHeight are reported instead. |
type? |
WindowSizeKind |
Report inner (viewport) or outer (browser window) dimensions. |
listenOrientation? |
boolean |
Also re-measure on orientationchange for engines that resize late. |
host? |
MaybeRefOrGetter<WindowSizeHost | null | undefined> |
Reactive window capability for alternate runtimes and tests. |
WindowSizeControls
Reactive size returned by useWindowSize.
| Member | Type | Description |
|---|---|---|
width |
Readonly<Ref<number>> |
Current width in CSS pixels. |
height |
Readonly<Ref<number>> |
Current height in CSS pixels. |
isSupported |
Readonly<Ref<boolean>> |
Whether a window capability is attached. false during server rendering. |