JAVASCRIPT

Building a Responsive Design Composable with Vue 3 `useMediaQuery`

Create a custom Vue 3 composable (`useMediaQuery`) to reactively track CSS media query states, enabling responsive logic in your components and abstracting away `window.matchMedia` details.

// composables/useMediaQuery.js
import { ref, onMounted, onUnmounted } from 'vue';

export function useMediaQuery(query) {
  const matches = ref(false);
  let mediaQueryList;

  const updateMatches = (event) => {
    matches.value = event.matches;
  };

  onMounted(() => {
    if (typeof window !== 'undefined' && window.matchMedia) {
      mediaQueryList = window.matchMedia(query);
      matches.value = mediaQueryList.matches;
      mediaQueryList.addEventListener('change', updateMatches);
    }
  });

  onUnmounted(() => {
    if (mediaQueryList) {
      mediaQueryList.removeEventListener('change', updateMatches);
    }
  });

  return matches;
}

// ComponentUsingMediaQuery.vue
<template>
  <div :class="{ 'mobile-layout': isMobile, 'desktop-layout': !isMobile }">
    <h3 v-if="isMobile">Mobile View</h3>
    <h3 v-else>Desktop View</h3>
    <p>Screen is {{ isMobile ? 'small' : 'large' }}.</p>
  </div>
</template>

<script setup>
import { useMediaQuery } from './composables/useMediaQuery';

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

<style scoped>
.mobile-layout {
  background-color: #ffe0b2;
  border: 1px solid orange;
  padding: 20px;
}
.desktop-layout {
  background-color: #c8e6c9;
  border: 1px solid green;
  padding: 20px;
}
</style>
How it works: This snippet provides a `useMediaQuery` composable for Vue 3 that allows components to reactively respond to CSS media query changes. The `useMediaQuery` function takes a media query string (e.g., `(max-width: 768px)`) and returns a reactive `ref` that indicates whether the query currently matches. It utilizes `window.matchMedia` to listen for changes. The `onMounted` and `onUnmounted` lifecycle hooks ensure that the event listener is properly attached and detached, preventing memory leaks. `ComponentUsingMediaQuery.vue` demonstrates how to consume this composable to apply different styles or render different content based on the screen size, centralizing responsive logic.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs