Skip to main content

Overview

Reactive media query composable with automatic cleanup. Integrates with window.matchMedia for responsive conditionals.

Features

  • Window matchMedia integration
  • Reactive query string support
  • SSR-safe (returns false on server)
  • Hydration-aware (defers client updates until hydrated)
  • Automatic listener cleanup on scope disposal
  • Supports both static and dynamic queries

Function Signature

function useMediaQuery(
  query: MaybeRefOrGetter<string>
): MediaQueryContext

Parameters

query
MaybeRefOrGetter<string>
CSS media query string (can be reactive).

Return Value

matches
Readonly<ShallowRef<boolean>>
Whether the media query currently matches.
query
ComputedRef<string>
The current media query string.
mediaQueryList
Readonly<ShallowRef<MediaQueryList | null>>
The underlying MediaQueryList (null on server).
stop
() => void
Stop listening and clean up.

Examples

Static query

import { useMediaQuery } from '@vuetify/v0'

const { matches } = useMediaQuery('(prefers-color-scheme: dark)')

watchEffect(() => {
  console.log('Dark mode:', matches.value)
})

Dynamic query

const minWidth = ref(768)
const { matches } = useMediaQuery(() => `(min-width: ${minWidth.value}px)`)

Manual cleanup

const { matches, stop } = useMediaQuery('(hover: hover)')

// Remove listener early
stop()

Responsive layout

const isMobile = useMediaQuery('(max-width: 768px)')
const isTablet = useMediaQuery('(min-width: 769px) and (max-width: 1024px)')
const isDesktop = useMediaQuery('(min-width: 1025px)')

Portrait orientation

const isPortrait = useMediaQuery('(orientation: portrait)')

Hover capability

const canHover = useMediaQuery('(hover: hover)')

Conditional component rendering

<script setup>
import { useMediaQuery } from '@vuetify/v0'

const isMobile = useMediaQuery('(max-width: 768px)')
</script>

<template>
  <MobileNav v-if="isMobile.matches.value" />
  <DesktopNav v-else />
</template>

Convenience Functions

usePrefersDark

function usePrefersDark(): MediaQueryContext
Check if the user prefers dark color scheme.
import { usePrefersDark } from '@vuetify/v0'

const { matches: prefersDark } = usePrefersDark()

watch(prefersDark, (dark) => {
  document.body.classList.toggle('dark', dark)
})

usePrefersReducedMotion

function usePrefersReducedMotion(): MediaQueryContext
Check if the user prefers reduced motion.
import { usePrefersReducedMotion } from '@vuetify/v0'

const { matches: prefersReducedMotion } = usePrefersReducedMotion()

const transitionDuration = computed(() => 
  prefersReducedMotion.value ? 0 : 300
)

usePrefersContrast

function usePrefersContrast(): MediaQueryContext
Check if the user prefers more contrast.
import { usePrefersContrast } from '@vuetify/v0'

const { matches: prefersContrast } = usePrefersContrast()

const contrastClass = computed(() => 
  prefersContrast.value ? 'high-contrast' : ''
)

Common Media Queries

Screen Size

// Mobile
useMediaQuery('(max-width: 768px)')

// Tablet
useMediaQuery('(min-width: 769px) and (max-width: 1024px)')

// Desktop
useMediaQuery('(min-width: 1025px)')

Orientation

// Portrait
useMediaQuery('(orientation: portrait)')

// Landscape
useMediaQuery('(orientation: landscape)')

Display Features

// High DPI screens
useMediaQuery('(min-resolution: 2dppx)')

// Touch capability
useMediaQuery('(hover: none) and (pointer: coarse)')

// Hover capability
useMediaQuery('(hover: hover)')

User Preferences

// Dark mode
useMediaQuery('(prefers-color-scheme: dark)')

// Light mode
useMediaQuery('(prefers-color-scheme: light)')

// Reduced motion
useMediaQuery('(prefers-reduced-motion: reduce)')

// High contrast
useMediaQuery('(prefers-contrast: more)')

SSR Behavior

  • During SSR, matches is always false
  • mediaQueryList is null on the server
  • Updates are deferred until client-side hydration completes
  • Query changes during hydration are queued and applied after hydration

Notes

  • Automatically removes event listeners on scope disposal
  • Reactive query changes are automatically handled
  • SSR-safe: returns false during server-side rendering
  • Hydration-aware: prevents SSR mismatch by deferring updates

Build docs developers (and LLMs) love