Responsive design is a frequently desired feature for web applications. As developers, we have to support a variety of devices and screen sizes. CSS is a great tool for simple use-cases and very efficient performance-wise. However, managing complex media queries may become burdensome even with the use of preprocessors (SASS, PostCSS, LESS, etc.).
Thanks to the MatchMedia API, Vue.js can greatly reduce the complexity of handling media queries and responsive design. It provides seamless integration with a component-based architecture, keeping a clean declarative and semantic approach.
In this article, you will explore features available to the vue-mq
plugin for media queries.
If you would like to follow along with this article, you will need:
Warning: This plugin relies on the matchMedia API to detect screen size changes. So, for older browsers and Internet Explorer, you should utilize Paul Irish’s matchMedia polyfill
This tutorial was verified with Node v15.8.0, npm
v7.5.4, Vue v12.6.11, and vue-mq
v1.0.1.
vue-mq
First, to use vue-mq
, open your terminal and navigate to your existing Vue project directory. Then, run the following command:
- npm install vue-mq@1.0.1
Next, with your code editor, edit your Vue project and import
the library:
import VueMq from 'vue-mq'
Define your custom breakpoints when registering the plugin. Keys are breakpoints and values are in pixels:
Vue.use(VueMq, {
breakpoints: {
sm: 450,
md: 1250,
lg: Infinity,
}
})
In this example, three breakpoints are defined. sm
for “small screens”. md
for “medium screens”. lg
for “large screens”.
You can also name your breakpoints after devices or anything that make sense to you:
Vue.use(VueMq, {
breakpoints: {
mobile: 450,
tablet: 900,
laptop: 1250,
desktop: Infinity,
}
})
In this example, four breakpoints are defined. A mobile
, tablet
, laptop
, and desktop
screen size.
vue-mq
with Conditional RenderingVery often when dealing with responsive design you will want to render elements conditionally.
For instance, display a specific menu for mobile devices only.
In order to accomplish that functionality, you can use the reactive $mq
property which is accessible inside each instance of a component. Its value will always be the current breakpoint.
<template>
<mobile-menu v-if="$mq === 'mobile'"></mobile-menu>
</template>
This component will render when the current screen size satisfies the conditional. If you defined the breakpoint for “mobile” to be 450 pixels, this component will render for screen sizes up to 450px.
vue-mq
also provides a shorthand for this syntax with a global mq-layout
component that acts as a conditional slot:
<template>
<mq-layout mq="mobile">
<mobile-menu></mobile-menu>
</mq-layout>
<mq-layout mq="tablet+">
<desktop-menu></desktop-menu>
</mq-layout>
</template>
Notice the plus sign (+
) after the “tablet” breakpoint name. This instructs vue-mq
to target the breakpoint and all the larger breakpoints as well.
vue-mq
with Prop ValuesAnother very common use-case is the computation of different values based on screen size.
For example, let’s say you want to display a responsive grid of items:
In other words, you just have to pass down a prop with different values according to screen size to the exact same grid component. It will have the responsibility to display the right number of columns.
vue-mq
provides a global filter for mapping breakpoints to values, using declarative rules:
<template>
<grid-component :column="$mq | mq({
phone: 2,
tablet: 3,
laptop: 4
})">
</grid-component>
</template>
Keep in mind that this plugin is enforcing a mobile-first approach. Values will default to the closest smaller breakpoints value if not defined explicitly.
If you omitted the “tablet” rule (tablet: 3
), it will fall back to the “phone” rule for “tablet” screen sizes and display 2 columns.
In the same way, if you need values that are more complex, move it in a computed
prop:
<template>
<responsive-title>{{ displayText }}</responsive-title>
</template>
<script>
export default {
computed: {
displayText() {
return this.$mq === 'mobile'
? 'You are on a mobile device'
: 'You are on a larger device'
}
}
}
</script>
This code will display "You are on mobile device"
or "You are on a larger device"
depending on your screen size.
vue-mq
with Responsive ClassesSometimes, you also want to change style quickly via CSS. The trick is to use a breakpoint name as a computed class on the element you want to style.
Here is an example with a Single-File Component:
<template>
<h1 class="responsive-title" :class="$mq">
Responsive Title
</h1>
</template>
<style>
.responsive-title.mobile { font-size: 1em; }
.responsive-title.desktop { font-size: 3em; }
</style>
This code will add a “mobile” or “desktop” class to the element depending on your screen size.
Here are some ideas for advanced usage in combination with other libraries:
In this article, you explored features available to the vue-mq
plugin for media queries.
vue-mq
offers shorthands for common use-cases while its flexibility lets you compose with media queries as you like.
If you’d like to learn more about Vue.js, check out our Vue.js topic page for exercises and programming projects.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!