Responsive Web Apps with Vuetify
VuetifyJs is a great Material Design Framework for VueJs. It comes with a ton of ready to use components. A “hidden champion” is the build in responsive system. This is not a component, but a declarative feature in some of its components. I’ll show you in this article how to create responsive text, forms, images and nearly everything — latter by using the breakpoint object. So if you want to create a web application that fits to every viewport sizes, VuetifyJs and of course this article is for you ;)
I assume that you’ve a running VueJs project with VuetifyJs, so I skip that project creation stuff. If you want to try this tutorial in a fresh setup, please read the Vuetify Quick Start tutorial. Another point: I’m using typescript (and I can recommend this). If you’re using Javascript things might be slightly different in your component, but this article we have nearly no coding, so this should no problem.
Breakpoints
Breakpoints in responsive web applications represents different view sizes. Obviously has a smart phone an other size than a tablet, or a notebook, or a normal PC monitor or a ultra wide screen. We as web developers should create applications, that work on every screen size — at least. I think it should work and look great on every screen size. To make this, the Material Design Spec gave breakpoints to us. One for each device type.
The screenshot above shows the Material Design viewport breakpoints. This breakpoint system is heavily used by VuetifyJs. You can checkout the documentation for further information.
Responsive Text
Some of the responsive text features come with Vuetify 2.3.0. So the one or other early bird has to use the beta version.
So what is responsive text? The text size depends on the screen size. If you have a headline on a ultra wide display, a font size of 80px may look better than 20px. On the other side — a 80px headline can smash the whole design on a tiny mobile phone. So responsive text makes definitely sense. Of course you can do this with css and media queries. But in VuetifyJs this is a ready to use declarative feature.
The image above shows how a heading and even the text can change on the view size. In Vuetify you can get this behavior simply by declaring different classes on your textelement:
<template>
<v-row class="pa-3">
<h1
class="
text-h4 [1]
text-md-h2 [2]
text-lg-h1 [2]
text-xl-h1 [2]
text-truncate" [3]
>This is my heading</h1>
<p
class="
text--secondary
text-caption
text-sm-body-2
text-md-body-1
text-lg-body-1
text-xl-body-1
text-justify">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut...
</p>
</v-row>
</template>/// @/components/ResponsiveText.vue
You’ve always a default text size class [1] which also covers the smallest breakpoint (xs). The default can be overwritten by using breakpoint classes for each breakpoint [2] — if you want a different text size according to the default. The pattern is always text-[breakpoint]-[fontsize]
. Especially in headings a great tool is text-truncate
, which cuts off the text if it doesn’t fit in the outer element.
Responsive Forms
Another big issue in creating responsive web applications are forms. They should be arranged, depending on the view size. Here can the great grid system play out its strength. Of course the grid system is not only useful using forms, but it’s a common case for responsive web applications. So I used a forms sample — it works always the same, regardless what you want to put onto the screen.
The grid system consists of rows and columns. Every “virtual” row has 12 “virtual” columns, which gives a grid of an arbitrary number of rows with 12 columns each. There’re two elements in vuetify — v-row
and v-column
. It’s important to understand, that you can place v-row
and v-column
into the grid system, but they doesn’t have to be equal to the static n to 12 grid.
The fields in the image above are all named with R(ow)[number]C(olumn)[number]. So you can see, how the fields move, in the grid system, on changing the view size. We can have a look on the first form row (R1C1, R1C2, R1C3) to make things more clear. On big screens, the first row (which is equal to the v-row
element) holds three fields in three v-col
elements. The first v-col
spreads over 6 virtual columns, the other two over 3 each. So they spread over 12 virtual columns in total.
Let’s have a look on the left bottom screenshot. Same form, lower view size. The first v-col
element spreads over 12 virtual columns, the other two over 6 each. So the v-row
element needs two rows à 12 virtual columns. The right bottom screenshot shows the same form in a very small view. The v-row
needs here three virtual rows and each v-col
spreads over 12 columns.
The question is — how can I get this behavior from VuetifyJs? Luckily this is the easy part. Simply as writing the number of virtual columns into the breakpoint attribute:
...
<v-row>
<v-col cols="12" md="6" lg="6" xl="6">
<v-text-field
label="Field R1C1"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3" lg="3" xl="3">
<v-text-field
label="Field R1C2"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="3" lg="3" xl="3">
<v-text-field
label="Field R1C3"
></v-text-field>
</v-col>
</v-row>
.../// @/components/ResponsiveForm.vue
There’s a breakpoint attribute for every Material Design breakpoint, except for xs
. This one is covered by the default attribute cols
. With the VuetifyJs grid system, you can create very powerful responsive layouts without any line of JavaScript code.
Responsive image size
The responsiveness of images comes from there ability to load the best image in size and quality for the device. For this the img
element offers the scrset
and sizes
attributes. There’re tons of great articles out in the web, so I’m not going to write an other one. The message for the VuetifyJs users is: These two attributes are there in the v-img
component as well. So you can use the standard responsive stuff with great features like lazy preload images or the contain
attribute.
...
<v-img
src="http://catify.de/.../village_1264.jpg"
lazy-src="http://catify.de/.../village_blur.jpg"
srcset="http://catify.de/.../village_600.jpg 600w,
http://catify.de/.../village_960.jpg 960w,
http://catify.de/.../village_1264.jpg 1264w,
http://catify.de/.../village_1904.jpg 1904w,
http://catify.de/.../village_2400.jpg 2400w"
width="100%"
></v-img>
.../// @/components/ResponsiveImage.vue
Responsive Type- or JavaScript
For every wish in responsiveness, that VuetifyJs not fulfills in a declarative way, they give a responsive breakpoint object to you. This can be used in computed properties, methods or nearly anywhere inside the VueJs context:
this.$vuetify.breakpoint
It supports you with information about the current breakpoint, conditionals, dimensions etc. You can check out the documentation for more. In the sample I’ve used this object, to switch from many icons in the app bar to a burger icon, for opening a hidden menu. This is simply done in one line of code [1]:
<script lang="ts">
import Vue from 'vue'
import { Component } from "vue-property-decorator"@Component
export default class ResponsiveActionIcons extends Vue {get shrink() {
return this.$vuetify.breakpoint.smAndDown [1]
}show() {
console.log("show menu...")
}}
</script>/// @/components/ResponsiveActionIcons.vue
The End
You can find the sources of my responsive VuetifyJs sample on a github repository. I hope you have enjoyed this article. Please leave a comment if you have any question or would like to give feedback.