npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue-responsiveness

v0.2.5

Published

A tiny, performant, and intuitive Vue 3 plugin for working with responsive breakpoints and media queries at runtime.

Downloads

2,185

Readme

Vue Responsiveness

A tiny, performant, and intuitive Vue 3 plugin for working with responsive breakpoints and media queries at runtime.

Total downloads Latest release License Dependencies Minzip size UMD gzip size Coverage SSR compatibility PRs welcome

Use it when you want Vue components to react to breakpoints, orientation, hover support, color scheme, reduced motion, and contrast preferences without manually wiring window.matchMedia.

Features

  • Vue-friendly API: use $matches in templates or useMatches() in <script setup>.
  • Breakpoint presets included: start with Bootstrap 5 by default, or switch to Tailwind CSS, Vuetify, Bulma, and more.
  • Custom breakpoints: define your own app-specific intervals with a plain object.
  • Media query support: react to viewport width, orientation, hover, prefers-color-scheme, prefers-contrast, and prefers-reduced-motion.
  • SSR safe: it does not touch window during server rendering.
  • Zero runtime dependencies: lightweight and built on the browser's native window.matchMedia.
  • Automatic cleanup: listeners are attached to MediaQueryList objects and cleaned up with the Vue app.

Installation

Use the package manager your project already uses.

| Package manager | Command | |-----------------|---------| | pnpm | pnpm add vue-responsiveness | | yarn | yarn add vue-responsiveness | | npm | npm install vue-responsiveness |

Quick start

Demo

Codesandbox

1. Register the plugin

In main.ts:

import { createApp } from 'vue'
import App from './App.vue'
import { VueResponsiveness } from 'vue-responsiveness'

createApp(App)
  .use(VueResponsiveness)
  .mount('#app')

That is enough to use the default Bootstrap 5 breakpoints. For other frameworks (Tailwind CSS, Vuetify, etc.), or your own intervals, see Breakpoint management.

2. Choose how to read responsive state

You can use either option below, or mix them in the same app. Use $matches for simple template conditions and useMatches() when you need responsive state in <script setup>.

Option A: use $matches in templates

Every component can read $matches in its template, without importing.

<template>
  <div>
    <p>Current breakpoint: {{ $matches.current || 'unknown' }}</p>

    <p v-if="$matches.md.min">
      This is visible on medium screens and larger.
    </p>

    <p v-if="$matches.sm.max">
      This is visible on small screens and smaller.
    </p>

    <p v-if="$matches.prefers.colorScheme === 'dark'">
      Dark mode is preferred.
    </p>
  </div>
</template>

Option B: use useMatches() in script setup

Use the composable when you need responsive state in computed values, watchers, or methods.

<script setup lang="ts">
import { computed } from 'vue'
import { useMatches } from 'vue-responsiveness'

const matches = useMatches()

const showSidebar = computed(() => matches.md.min)
</script>

<template>
  <main>
    <aside v-if="showSidebar">
      Sidebar navigation
    </aside>

    <nav v-else>
      Mobile navigation
    </nav>
  </main>
</template>

You can also use helper methods:

const showDesktopNav = computed(() => matches.isMin('lg'))
const showMobileNav = computed(() => matches.isMax('sm'))
const isTabletLayout = computed(() => matches.isOnly('md'))

Breakpoint management

Use a preset

The plugin uses Presets.Bootstrap_5 by default. To use a different preset, pass it as the second argument to app.use().

import { createApp } from 'vue'
import App from './App.vue'
import { VueResponsiveness, Presets } from 'vue-responsiveness'

createApp(App)
  .use(VueResponsiveness, Presets.Tailwind_CSS)
  .mount('#app')

Available presets:

Ant_Design, Bootstrap_3, Bootstrap_4, Bootstrap_5, Bulma, Chakra, Foundation, Ionic, Master_CSS, Material_Design, Materialize, Material_UI, Quasar, Semantic_UI, Skeleton, Tailwind_CSS, Vuetify, Windi_CSS

Presets.Bootstrap_5 = {
  xs: 0,
  sm: 576,
  md: 768,
  lg: 992,
  xl: 1200,
  xxl: 1400,
}

Vue Responsiveness is designed to have one app-wide breakpoint configuration. Register the plugin once, close to createApp(), so all components read from the same $matches object.

Define custom breakpoints

Pass an object whose keys are your breakpoint names and whose values are the minimum width in pixels. The plugin calculates each breakpoint's maximum width from the next breakpoint.

app.use(VueResponsiveness, {
  small: 0,
  medium: 777,
  large: 1234
})

Then use those names in templates:

<!-- @media (min-width: 777px) and (max-width: 1233.9px) -->
<template v-if="$matches.medium.only">
  <TwoColumnLayout />
</template>

API Reference

$matches and useMatches() expose the same reactive object. Use $matches in templates and useMatches() in JavaScript or TypeScript.

Breakpoint status properties

Each breakpoint key, such as sm, md, lg, or one of your custom names, contains three booleans.

| Name | Type | Description | Example Access | |-----------------------|-----------|-------------|----------------| | current | string | The breakpoint interval that currently matches. | $matches.current | | [breakpointKey].min | boolean | true at this breakpoint width and above. | $matches.md.min | | [breakpointKey].max | boolean | true up to and including this breakpoint range. | $matches.lg.max | | [breakpointKey].only| boolean | true only inside this breakpoint range. | $matches.sm.only |

Breakpoint helper methods

These are handy in computed values and methods.

| Name | Type | Description | Example usage | |---------------------|------------------------------|-------------|---------------------------------------| | isMin(breakpoint) | (breakpointKey) => boolean | Matches at this breakpoint and above. | matches.isMin('md') | | isMax(breakpoint) | (breakpointKey) => boolean | Matches inside this breakpoint range and below. | matches.isMax('sm') | | isOnly(breakpoint)| (breakpointKey) => boolean | Matches only inside this breakpoint range. | matches.isOnly('lg') |

Additional media query properties

These values mirror common CSS media queries, but are available directly in Vue.

| Name | Type | Description | Media query equivalent | |-------------------------|-----------------------------------|-------------|------------------------| | orientation | 'portrait' \| 'landscape' | The current device orientation | @media (orientation: *) | | hover | 'none' \| 'hover' | The hover capability of the device | @media (hover: *) | | prefers.reducedMotion | 'no-preference' \| 'reduce' | User preference for reduced motion | @media (prefers-reduced-motion: *) | | prefers.colorScheme | 'light' \| 'dark' | User preference for color scheme | @media (prefers-color-scheme: *) | | prefers.contrast | 'no-preference' \| 'more' \| 'less' \| 'custom' | User preference for contrast | @media (prefers-contrast: *) |

Testing

When testing a component that uses $matches, install the plugin through Vue Test Utils global.plugins.

import { shallowMount } from '@vue/test-utils'
import MyComponent from './MyComponent.vue'
import { VueResponsiveness } from 'vue-responsiveness'

describe('<MyComponent />', () => {
  it('should render', () => {
    const wrapper = shallowMount(MyComponent, {
      global: {
        plugins: [VueResponsiveness]
      }
    })

    expect(wrapper.exists()).toBe(true)
  })
})

How it works

  • Vue Responsiveness uses window.matchMedia(queryString), the same browser API behind CSS media queries.
  • It listens to change events on MediaQueryList objects, so updates happen only when a query starts or stops matching.
  • It avoids global resize listeners and keeps one responsive state object per Vue app.
  • It is SSR safe because browser-only APIs are read after the plugin is installed in the client.

Questions and issues

Found something confusing, broken, or missing? Open an issue.