useWindowSize

Layout/Viewport

A React hook that tracks the browser window dimensions in real-time, perfect for responsive layouts and dynamic UI adjustments.

Demo

Try resizing your browser window to see the dimensions update in real-time:

Window Width
0px
Window Height
0px
Responsive Breakpoints
Mobile (<640px): Active
Small (≥640px): Inactive
Medium (≥768px): Inactive
Large (≥1024px): Inactive
Extra Large (≥1280px): Inactive
Aspect Ratio
NaN(width / height)

Installation

npm install @thibault.sh/hooks

Usage

import { useWindowSize } from '@thibault.sh/hooks/useWindowSize';

function ResponsiveComponent() {
  const { width, height } = useWindowSize();

  return (
    <div>
      <p>Window dimensions: {width}x{height}</p>
      {width < 768 ? (
        <MobileLayout />
      ) : (
        <DesktopLayout />
      )}
    </div>
  );
}

API

Returns

Object containing current window width and height

Features

  • Real-time Updates

    Automatically updates when window dimensions change

  • SSR Compatible

    Safely handles server-side rendering with default dimensions

  • Performance Optimized

    Uses debounced resize event listener to prevent excessive re-renders

  • Type Safe

    Full TypeScript support with proper type definitions

Responsive Grid Example

import { useWindowSize } from '@thibault.sh/hooks/useWindowSize';

function ResponsiveGrid({ items }: { items: Array<any> }) {
  const { width } = useWindowSize();

  // Calculate optimal number of columns based on window width
  const columns = Math.max(1, Math.floor(width / 300)); // 300px min column width
  const gridStyle = {
    display: 'grid',
    gridTemplateColumns: `repeat(${columns}, 1fr)`,
    gap: '1rem'
  };

  return (
    <div style={gridStyle}>
      {items.map((item, index) => (
        <div key={index} className="card">
          {/* Card content */}
        </div>
      ))}
    </div>
  );
}

Dynamic Canvas Example

import { useWindowSize } from '@thibault.sh/hooks/useWindowSize';
import { useEffect, useRef } from 'react';

function ResponsiveCanvas() {
  const { width, height } = useWindowSize();
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    // Update canvas dimensions
    canvas.width = width;
    canvas.height = height;

    // Get context and draw
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    // Example: Draw a responsive circle in the center
    const centerX = width / 2;
    const centerY = height / 2;
    const radius = Math.min(width, height) / 4;

    ctx.beginPath();
    ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
    ctx.fillStyle = '#f97316';
    ctx.fill();
  }, [width, height]);

  return <canvas ref={canvasRef} />;
}

Conditional Rendering Example

import { useWindowSize } from '@thibault.sh/hooks/useWindowSize';

function AdaptiveUI() {
  const { width } = useWindowSize();

  const isMobile = width < 768;
  const isTablet = width >= 768 && width < 1024;
  const isDesktop = width >= 1024;

  return (
    <div>
      {isMobile && (
        <nav className="mobile-nav">
          <HamburgerMenu />
        </nav>
      )}
      
      {isTablet && (
        <nav className="tablet-nav">
          <IconMenu />
        </nav>
      )}
      
      {isDesktop && (
        <nav className="desktop-nav">
          <FullMenu />
        </nav>
      )}

      <main className={
        isDesktop ? 'p-8' : 
        isTablet ? 'p-6' : 
        'p-4'
      }>
        {/* Content */}
      </main>
    </div>
  );
}