Skip to content

responsive-media

Reactive boolean state from CSS media queries and element dimensions for Vanilla JS, Vue 3, and React 19+ — AND/OR conditions, container queries, ordered breakpoint helpers, rich subscription API, CSS vars sync, SSR-safe — with no required peer dependencies.

Features

  • Framework-agnostic coreReactiveResponsiveState and ContainerState work with Vanilla JS, any signals library, or any framework; Vue and React are optional peer dependencies
  • Viewport breakpoints — backed by window.matchMedia; conditions combined with AND (flat array) or OR (nested array); raw media type support for print, screen, etc.
  • Full condition vocabularymin/max-width, min/max-height, orientation, aspect-ratio, prefers-color-scheme, prefers-reduced-motion, prefers-contrast, hover, pointer, forced-colors, resolution, display-mode, and raw
  • Container queries (JS-side)ContainerState tracks an element's dimensions via ResizeObserver and evaluates breakpoint conditions in JavaScript; identical API to viewport state
  • Rich subscription APIsubscribe, on, onEnter, onLeave, once, onNextChange, onBreakpointChange, waitFor; optional debounce for subscribe; per-key listeners are never debounced
  • Ordered breakpoint helperscurrent, isAbove(), isBelow(), between() for semantic viewport comparisons; order derived from config key insertion or explicit order option
  • UtilitiessyncCSSVars (CSS custom properties), emitDOMEvents (DOM CustomEvents), toSignal (any signals library — Preact, Angular, SolidJS, Vue), match (pick value by first active breakpoint), subscribeMediaQuery (raw single query)
  • Vue 3 adapteruseResponsive, useBreakpoints, useMediaQuery, useContainerState; fully reactive in templates and computed; ResponsivePlugin for global config
  • React 19+ adapter — same four hooks; useSyncExternalStore for safe concurrent rendering; SSR-safe (false on server)
  • PresetsTailwindPreset, BootstrapPreset, AccessibilityPreset out of the box; user-preference queries (dark, reducedMotion, highContrast, print, …)
  • SSR-safe — all APIs check for window / matchMedia / ResizeObserver before use; hydrate() prevents layout shift on the client
  • TypeScript — full generics; ConfigToState<T> infers a boolean-state type from any config object

Installation

bash
npm install responsive-media

No required peer dependencies. Vue and React adapters are available automatically when the respective package is installed:

bash
npm install vue@>=3.3     # for Vue composables
npm install react@>=19    # for React hooks

Quick start

ts
import { responsiveState, setResponsiveConfig } from 'responsive-media'

setResponsiveConfig({
  mobile: [{ type: 'max-width', value: 767 }],
  tablet: [
    { type: 'min-width', value: 768 },
    { type: 'max-width', value: 1023 },
  ],
  desktop: [{ type: 'min-width', value: 1024 }],
})

// Read current state
console.log(responsiveState.proxy.mobile) // true / false

// Subscribe to changes
const stop = responsiveState.subscribe((state) => {
  console.log('desktop:', state.desktop)
})

// Cleanup
stop()