Mobile Adaptation Techniques for Vue.js Development
This article explains how to adapt Vue.js web pages for diverse mobile devices by configuring the viewport meta tag, using relative and viewport units, applying flex layouts, handling fixed positioning issues, implementing route transitions, and leveraging useful plugins and component registration methods.
Compared with PC screens, mobile devices have a wide variety of resolutions, making viewport adaptation the first challenge for developers.
In the <head> of a mobile page you will often see the following meta tag:
<meta name='viewport' content='width=device-width,initial-scale=1,user-scale=no' />The meta tag defines the page's scaling behavior. Understanding the different viewport widths is essential:
layout viewport – the width of the page layout.
visual viewport – the width of the browser window that the user actually sees.
ideal viewport – the device's native viewport width (device‑width).
Setting width=device-width aligns the layout viewport with the ideal viewport, while initial-scale=1 sets the initial zoom ratio. user-scale=no disables user zoom.
When the visual and layout viewports match the ideal viewport, scrollbars disappear and the page displays consistently across devices.
Using Relative Units
rem is calculated from the root html element's font‑size . A common practice is to set the root font size to one‑tenth of the viewport width:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';Tools like pxtorem can automatically convert px to rem during build.
Viewport Units
Viewport units divide the viewport into 100 parts:
1vw = 1% of viewport width
1vh = 1% of viewport height
vmin = the smaller of vw and vh
vmax = the larger of vw and vh
Unlike rem , viewport units need no JavaScript, though they have slightly lower compatibility. Plugins such as postcss-px-to-viewport can convert px to these units at build time.
Modifying the Viewport Dynamically
You can fix the layout viewport to a design width (e.g., 750 px) by calculating the appropriate scale:
(function () {
const width = document.body.clientWidth || window.innerWidth;
const scale = width / 750;
const content = 'width=750, initial-scale=' + scale + ', minimum-scale=' + scale + ', maximum-scale=' + scale + ', viewport-fit=cover';
document.querySelector('meta[name="viewport"]').content = content;
})();After this, the layout viewport stays at 750 px on any device, allowing you to design directly against the mockup size.
Layout Styles
While many layout methods exist, avoid styles that cause compatibility problems. Use position:fixed cautiously because on iOS the soft keyboard can disable it, and any ancestor with transform creates a new stacking context that changes the reference frame.
Prefer Flexbox
Flexbox offers good mobile compatibility and can easily implement a typical header‑content‑footer layout.
Page Transitions
In Vue, vue‑router manages routes. Adding a <transition> wrapper around <router‑view> enables animated page switches. By storing a numeric meta.depth on each route and comparing to.meta with from.meta , you can apply different animations for forward, backward, or replace navigation.
<template>
<transition :name="transitionName">
<router-view></router-view>
</transition>
</template>
<script>
export default {
data() { return { transitionName: 'fade' } },
watch: {
'$route'(to, from) {
const toDepth = to.meta;
const fromDepth = from.meta;
if (fromDepth > toDepth) this.transitionName = 'fade-left';
else if (fromDepth < toDepth) this.transitionName = 'fade-right';
else this.transitionName = 'fade';
}
}
}
</script>For simpler navigation, the vue‑navigation plugin can handle forward/backward animations and preserve page state.
Bottom Navigation Bar
When a route matches a router‑link , the link receives an active class ( router‑link‑active by default). Use active‑class or exact‑active‑class to customize the styling.
Route Guards
Typical mobile route guards check authentication. Define a whitelist of routes that do not require login, and for protected routes verify a token before allowing navigation. Permissions can be expressed via a roles array in meta and compared with the user’s roles from the backend.
const whiteList = ['/login'];
router.beforeEach((to, from, next) => {
const hasToken = store.getters.auth;
if (hasToken) {
if (to.path === '/login') next({ path: '/' });
else {
const needRoles = to.meta && to.meta.roles && to.meta.roles.length > 0;
if (needRoles) {
const hasRoles = store.state.user.roles.some(r => to.meta.roles.includes(r));
hasRoles ? next() : next('/403');
} else next();
}
} else {
whiteList.includes(to.path) ? next() : next('/login');
}
});Automatic Component Registration
Frequently used components can be registered globally using require.context :
export default function registerComponent(Vue) {
const modules = require.context('./', false, /\w+.vue$/);
modules.keys().forEach(fileName => {
const component = modules(fileName);
const name = fileName.replace(/^\.\/(.*)\.\w+$/, '$1');
Vue.component(name, component.default || component);
});
}v‑model Binding
v‑model is syntactic sugar for a value prop and an input event. It can be customized via the model option to use different prop/event names.
Vue.component('my-checkbox', {
model: { prop: 'checked', event: 'change' },
props: { value: String, checked: { type: Number, default: 0 } }
});Using Components as Plugins
Components can be instantiated manually and mounted to document.body :
export default function create(Component, props) {
const vm = new Vue({
render(h) { return h(Component, { props }); }
}).$mount();
document.body.appendChild(vm.$el);
const comp = vm.$children[0];
comp.remove = function () { document.body.removeChild(vm.$el); vm.$destroy(); };
return comp;
}Third‑Party Component Libraries
Popular mobile Vue UI libraries include VantUI, Vux, and Mint‑UI. VantUI supports on‑demand import, theme customization, and SSR. Theme variables can be overridden in webpack.config.js or vue.config.js using less-loader options.
Common Plugins
better-scroll provides smooth scrolling for mobile scenarios, while swiper (used via vue-awesome-swiper ) offers carousel functionality.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.