Core Concepts
Config format: MediaQueryConfig
Each breakpoint is described by a MediaQueryConfig — an array of conditions combined with AND, or a nested array of groups combined with OR.
AND (flat array)
// (min-width: 768px) and (max-width: 1023px)
;[
{ type: 'min-width', value: 768 },
{ type: 'max-width', value: 1023 },
]OR (nested array)
// (max-width: 600px), (orientation: portrait) and (max-width: 1024px)
;[
[{ type: 'max-width', value: 600 }],
[
{ type: 'orientation', value: 'portrait' },
{ type: 'max-width', value: 1024 },
],
]Raw media type
Use type: 'raw' to insert a value verbatim — useful for media types like print or screen:
// Matches 'print' media type
;[{ type: 'raw', value: 'print' }][
// screen and (max-width: 600px)
({ type: 'raw', value: 'screen' }, { type: 'max-width', value: 600 })
]Supported condition types
type | Example value | Generated query |
|---|---|---|
min-width | 768 | (min-width: 768px) |
max-width | 1023 | (max-width: 1023px) |
min-height | 600 | (min-height: 600px) |
max-height | 900 | (max-height: 900px) |
orientation | 'portrait' | (orientation: portrait) |
aspect-ratio | '16/9' | (aspect-ratio: 16/9) |
prefers-color-scheme | 'dark' | (prefers-color-scheme: dark) |
prefers-reduced-motion | 'reduce' | (prefers-reduced-motion: reduce) |
prefers-contrast | 'more' | (prefers-contrast: more) |
hover | 'none' | (hover: none) |
pointer | 'coarse' | (pointer: coarse) |
forced-colors | 'active' | (forced-colors: active) |
resolution | '2dppx' | (resolution: 2dppx) |
display-mode | 'standalone' | (display-mode: standalone) |
raw | 'print' | print (verbatim) |
Global singleton
The library exports a pre-configured singleton responsiveState initialized with the default ResponsiveConfig (mobile / tablet / desktop).
import { responsiveState, setResponsiveConfig, getResponsiveMediaQueries } from 'responsive-media'
// Re-configure the singleton
setResponsiveConfig(
{
sm: [{ type: 'max-width', value: 767 }],
lg: [{ type: 'min-width', value: 1024 }],
},
{
order: ['sm', 'lg'], // for isAbove / isBelow / between
debounce: 50, // ms — throttle subscribe() listeners
},
)
// Read a stable snapshot
const { sm, lg } = responsiveState.getState()
// Live proxy access (never debounced)
console.log(responsiveState.proxy.sm)
// Get the generated CSS strings
const mq = getResponsiveMediaQueries()
// { sm: '(max-width: 767px)', lg: '(min-width: 1024px)' }Default config (ResponsiveConfig)
| Key | Range |
|---|---|
mobile | ≤ 600px |
tablet | 601 – 960px |
desktop | ≥ 961px |
createResponsiveState: isolated instances
Create independent instances — useful for per-request SSR, multiple independent contexts, or testing:
import { createResponsiveState, TailwindPreset, TailwindOrder } from 'responsive-media'
const layoutState = createResponsiveState(TailwindPreset, {
order: [...TailwindOrder],
})
const themeState = createResponsiveState({
dark: [{ type: 'prefers-color-scheme', value: 'dark' }],
reducedMotion: [{ type: 'prefers-reduced-motion', value: 'reduce' }],
})
layoutState.subscribe((s) => console.log('layout:', s))
themeState.subscribe((s) => console.log('theme:', s))
// Cleanup when done (e.g. per-request SSR)
layoutState.destroy()ContainerState: element container queries
ContainerState tracks an element's dimensions via ResizeObserver and evaluates breakpoint conditions in JavaScript — the same concept as CSS Container Queries, but in JS.
The API is identical to ReactiveResponsiveState — all subscription methods work the same way.
import { createContainerState } from 'responsive-media/container'
// or: import { createContainerState } from 'responsive-media';
const card = document.querySelector('.card')!
const cardState = createContainerState(
card,
{
compact: [{ type: 'max-width', value: 300 }],
normal: [
{ type: 'min-width', value: 301 },
{ type: 'max-width', value: 599 },
],
wide: [{ type: 'min-width', value: 600 }],
},
{
order: ['compact', 'normal', 'wide'],
},
)
// Reactive class toggling
cardState.on('compact', (v) => card.classList.toggle('card--compact', v))
// Sync CSS custom properties: --card-compact: 1; --card-wide: 0; …
cardState.syncCSSVars({ prefix: '--card-' })
// Get @container-compatible query strings
const strings = cardState.getMediaQueries()
// { compact: '(max-width: 300px)', wide: '(min-width: 600px)' }
// Cleanup
cardState.destroy()Supported condition types for ContainerState
max-width, min-width, max-height, min-height, orientation, aspect-ratio