Tutorial

Write Element-Based Responsive Components in Vue.js

Published on April 30, 2018
author

Joshua Bemenderfer

Write Element-Based Responsive Components in Vue.js

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.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Joshua Bemenderfer

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


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!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.