JAVASCRIPT
Vue 3 useMediaQuery Composable
Create a reactive Vue 3 composable to track CSS media query states, enabling dynamic UI adjustments based on viewport characteristics.
import { ref, onMounted, onUnmounted } from 'vue';
/**
* A Vue 3 Composable to reactively track CSS media query states.
* @param {string} query The media query string, e.g., '(min-width: 768px)'
* @returns {Ref<boolean>} A reactive ref indicating if the media query matches.
*/
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; // Initial check
mediaQueryList.addEventListener('change', updateMatches);
}
});
onUnmounted(() => {
if (mediaQueryList) {
mediaQueryList.removeEventListener('change', updateMatches);
}
});
return matches;
}
// Example Usage in a component:
// <template>
// <div>
// <p>Is desktop view? {{ isDesktop }}</p>
// <p v-if="isDesktop">Welcome to the desktop layout!</p>
// <p v-else>Viewing on a mobile/tablet device.</p>
//
// <p>Is print mode? {{ isPrint }}</p>
// <p v-if="isPrint">This content is optimized for printing.</p>
// </div>
// </template>
//
// <script setup>
// import useMediaQuery from './composables/useMediaQuery';
//
// const isDesktop = useMediaQuery('(min-width: 1024px)');
// const isPrint = useMediaQuery('print');
// </script>
export default useMediaQuery;
How it works: The `useMediaQuery` composable provides a reactive way to determine if a given CSS media query currently matches the document. It leverages `window.matchMedia` and its `addEventListener` for the 'change' event to listen for updates. On component mount, it checks the initial state and then continuously updates a reactive `matches` ref whenever the media query state changes (e.g., on window resize or device orientation change). This is extremely useful for building responsive UIs in Vue, allowing components to dynamically render content or adjust behavior based on screen size, print mode, or other media features without relying solely on CSS.