JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1217
  • Score
    100M100P100Q100346F
  • License MIT

Package Exports

  • vue-responsiveness

Readme

Vue Responsiveness

What - tiny plugin for working with responsiveness intervals, focused on runtime performance and great DX.
Why - I'm obsessed with both runtime performance (see how it works) and ease of use.

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

Installation

yarn

yarn add vue-responsiveness

npm

npm i vue-responsiveness

Basic demo

Codesandbox

Usage

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>

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

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

Breakpoint presets:

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

app.use(VueResponsiveness, Presets.Tailwind_CSS)

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

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

Here's the list of currently available presets:

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

Notes:

  • If you maintain a CSS framework (or use one often) and want it added as a preset, 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.
  • You can define your own responsiveness intervals, see Bespoke intervals section below.
  • You can't define more than one preset and have them working in different parts of the same app. This functionality will not be added to the plugin, as it would mean no longer having a single instance of the plugin per app, which would be a performance hit for the majority of use cases. If this functionality is ever needed, consider asking it on StackOverflow, let me know about it (either opening an issue on the repo or tagging my SO profile) and I'll provide a solution.

Bespoke intervals:

app.use(VueResponsiveness, {
  small: 0,
  medium: 777,
  large: 1234
})
<!-- @media (min-width: 777px) and (max-width: 1233.9px) -->
<template v-if="$matches.medium.only">
  ...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() or <script 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'))

Testing:

Add plugin to global.plugins when testing components using the plugin's API: Example

import MyComponent from './MyComponent.vue'
import { VueResponsiveness } from 'vue-responsiveness'
describe('<MyComponent />', () => {
  it('should render', () => {
    const wrapper = shallowMount(MyComponent, {
      global: {
        plugins: [VueResponsiveness]
      }
    })
    // test here    
  })
})

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
  • only one instance per app (much lighter than having one instance per component needing it)
  • in terms of memory and/or CPU consumption, using window.matchMedia is a few hundred times lighter than using the "traditional" resize event listener method

Got issues?

Let me know!

Happy coding!
:: }<(((*> ::