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 core —
ReactiveResponsiveStateandContainerStatework 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 forprint,screen, etc. - Full condition vocabulary —
min/max-width,min/max-height,orientation,aspect-ratio,prefers-color-scheme,prefers-reduced-motion,prefers-contrast,hover,pointer,forced-colors,resolution,display-mode, andraw - Container queries (JS-side) —
ContainerStatetracks an element's dimensions viaResizeObserverand evaluates breakpoint conditions in JavaScript; identical API to viewport state - Rich subscription API —
subscribe,on,onEnter,onLeave,once,onNextChange,onBreakpointChange,waitFor; optional debounce forsubscribe; per-key listeners are never debounced - Ordered breakpoint helpers —
current,isAbove(),isBelow(),between()for semantic viewport comparisons; order derived from config key insertion or explicitorderoption - Utilities —
syncCSSVars(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 adapter —
useResponsive,useBreakpoints,useMediaQuery,useContainerState; fully reactive in templates andcomputed;ResponsivePluginfor global config - React 19+ adapter — same four hooks;
useSyncExternalStorefor safe concurrent rendering; SSR-safe (falseon server) - Presets —
TailwindPreset,BootstrapPreset,AccessibilityPresetout of the box; user-preference queries (dark,reducedMotion,highContrast,print, …) - SSR-safe — all APIs check for
window/matchMedia/ResizeObserverbefore 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-mediaNo 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 hooksQuick 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()