Skip to content

codemonk-digital/vue-responsiveness

Repository files navigation

Vue Responsiveness

Total Downloads Latest Release License Dependencies unpkg umd min:gzip size CircleCI Unit tests coverage SSR compatibility status PRs Welcome

Tiny plugin for working with responsiveness intervals, focused on - ease of use - runtime performance.

To be fair, I am a bit obsessed with both performance and ease of use. If curios, scroll down to How it works.

Installation

yarn

yarn add vue-responsiveness

npm

npm i vue-responsiveness

Basic demo

https://codesandbox.io/s/kind-grass-93d5q4

Usage

Note: The default config value is set to Bootstrap 5's responsiveness breakpoints preset:

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

main.ts

import { VueResponsiveness } from 'vue-responsiveness'

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

in any <template />:

<!-- @media (min-width: 576px) -->
<template v-if="$matches.sm.min">
     ...content
</template>

<SomeComponent v-if="$matches.sm.max">
  <!-- @media (max-width: 767.9px) -->
  ...content
</SomeComponent>

<div v-if="$matches.sm.only">
  <!-- @media (min-width: 576px) and (max-width: 767.9px) -->
  ...content
</div>

Breakpoint presets:

import { VueResponsiveness, Presets } from "vue-responsiveness";

app.use(VueResponsiveness, Presets.Tailwind_CSS)

Available presets:

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

Notes:

  • If you maintain a CSS framework (or use one often) and want its preset added, open an issue or a PR.
  • If you spot any inconsistency in the presets (either my typo or some library update), please, let me know, I'll correct it.

Bespoke intervals:

app.use(VueResponsiveness, {
  small: 0,
  medium: 777,
  large: 1234
})
<template v-if="$matches.medium.only">
  <!-- @media (min-width: 777px) and (max-width: 1233.9px) -->
  ...content
</template>

Hide components, (while still rendering them) - usage with v-show:

<SomeComponent /> below will be rendered at all times but will only be displayed on md and below:

<!-- rendered at all times (keeps listeners while hidden), but only displayed on 
  @media (max-width: 991.9px) -->
<SomeComponent v-show="$matches.md.max" />

Use in setup():

import { useMatches } from 'vue-responsiveness'

const matches = useMatches()

const currentInterval = computed(() => matches.interval)
const trueOnSmOnly = computed(() => matches.isOnly('sm'))
const trueOnMdAndAbove = computed(() => matches.isMin('md'))

How it works:

  • uses the native window.matchMedia(queryString) and only reacts to changes in the query's matches value. It's the same API powering CSS media queries.
  • listeners are placed on the MediaQueryList instances, meaning they are garbage collected as soon as the app is unmounted, without leaving bound events behind on <body> or window object.
  • no global pollution
  • having it app-wide is lighter than having listeners bound by each component using it
  • in terms of memory and/or CPU consumption, using window.matchMadia is a few hundred times lighter than using the "traditional" resize event listener method

Got issues?

Let me know!