Write Element-Based Responsive Components in Vue.js

Joshua Bemenderfer

CSS Media Queries are great. They allow you to change the styles of your components based on the size of the browser viewport. But they’re not always what you need. Sometimes you want to change your components’ styles based on the width of the components themselves, not the width of the window. Now, you could wait until CSS Element Queries finally make it into some finalized spec and get shipped in evergreen browsers, but there’s a much easier solution for Vue.js components that requires far less waiting: vue-responsive-component.

This guide assumes you have a Vue.js project already set up. If not, go ahead and start a new Vue project using vue-cli 3.0 and the default options. $ vue create my-new-project and hitting enter a couple times should be sufficient.

Install vue-responsive-components

vue-responsive-components is a library that uses ResizeObserver (through a MutationObserver-based polyfill) to performantly determine when an element resizes. Go ahead and grab the library now:

$ npm install --save vue-responsive-components

Responsive Components

Let’s go ahead and create a file called Responsive.vue in our components directory. Yes, it’s about the most creative name I could think of.

components/Responsive.vue

<template>
  <!--
    v-responsive takes a set of objects
    where the keys are class names and the values are
    functions that take an element and return a boolean.
    If the functions return true, then the classes will be applied.

    In this case, if the component is less than 800 pixels wide,
    the `small` class will be applied.
    If the component is less than 400 pixels wide, both the `small`
    and `tiny` classes will be applied.
  -->
  <div class="responsive-component" v-responsive="{
    tiny: el => el.width < 400,
    small: el => el.width < 800
  }">
  </div>
</template>

<script>
import { ResponsiveDirective } from "vue-responsive-components"

export default {
  directives: {
    responsive: ResponsiveDirective
  }
}
</script>

<style scoped>
.responsive-component {
  height: 200px;
  background: red;
}

/* Applied when the component is less than 800px wide. */
.responsive-component.small {
  background: green;
}

/* Applied when the component is less than 400px wide. */
.responsive-component.tiny {
  background: blue;
}
</style>

Alright, so this is just about the world’s most boring component. It will just be a big red box, unless the element size is less than 800 pixels, in which case it will be a green box, if it gets any smaller, say, 400 pixels, it will be a blue box. Yippie.

Of course, since each of those queries takes a function as an argument, you can do far more advanced things with them.

So… How do we test our component?

Go ahead and open App.vue (or whichever component you wish to embed the responsive component inside)

App.vue

<template>
  <!--
    This gives us convenient resize handles to shrink and resize
    the parent of the responsive component.
  -->
  <div id="app" style="resize: horizontal; overflow: hidden;">
    <Responsive></Responsive>
  </div>
</template>

<script>
import Responsive from './components/Responsive.vue'

export default {
  components: {
    Responsive
  }
}
</script>

You should now find that your colored box componenty-thingy will change color when you resize the parent component.

This could be used for all sorts of things! List cards that dynamically adapt to their environment regardless of their layout, and more! Use your imagination!

For more information about vue-responsive-components, take a look at the official docs.

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#