Improve Vue.js Accessibility with vue-announcer

Joshua Bemenderfer

The defining characteristic of Single-Page-Applications, like those commonly made with Vue.js, is that they take over navigation inside the page with JavaScript instead of leaving it to the browser like normal websites. Unfortunately, when this happens, accessibility can easily fall by the wayside. Screen readers may not pick up route changes, which may leave visually-impaired users disoriented. vue-announcer should help alleviate the problem, by allowing you to announce changes to screen readers. It’s useful for route changes, notifications, announcements, and pretty much any dynamic DOM modification. All you have to do is tell it when and what to announce.

Getting Started

Go ahead and install vue-announcer. 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. Running $ vue create my-new-project and hitting enter a couple times should be sufficient.

$ npm install --save vue-announcer

Next, enable the plugin. All it does is register the component:


import Vue from 'vue';
import VueAnnouncer from 'vue-announcer';
import App from './App.vue';


new Vue({
  el: '#app',
  render: h => h(App)

Announcing Route Changes

Now, one of the main features of vue-announcer is the ability to automatically announce route changes when you navigate somewhere in your app.

The simplest way to configure it is just to pass your router instance when enabling the VueAnnouncer plugin, like so:


// the import stuff from Getting Started above.
// ...
import VueRouter from 'vue-router';

import Home from './routes/Home.vue';
import About from './routes/About.vue';


const routes = [
    path: '/home',
    component: Home
    path: '/about',
    component: About

const router = new VueRouter({ routes });

Vue.use(VueAnnouncer, {}, router);

// Everything else from the section above.
// ...

That will do the trick if you’re not looking for anything custom, but what if you want to change the message?


// Just change this line and set the complimentRoute property.
Vue.use(VueAnnouncer, {
  complimentRoute: 'is ready!' // {route} is ready!
}, router);

Or would like to have different messages for each route?


// Add meta: { announcer: 'My Message' } to the route configuration for each route.

const routes = [
    path: '/home',
    component: Home,
    meta: {
      // "Home route is ready!" when combined with the configuration above.
      announcer: 'Home route'
    path: '/about',
    component: About,
    meta: {
      // "About route (aboute?) is ready!" when combined with the configuration above.
      announcer: 'About route (aboute?)'

Manual Announcements

vue-announcer also helps you with informing screen readers of changes to dynamic content. For example, custom status updates or notifications. There’s no real way to do this automatically, so you’ll have to manually trigger and set messages.

When you write announcements, think through how a visually-impaired user would understand them, and try to word your messages accordingly.

To trigger a manual announcement, you’ll first need a mount point for the vue-announcer component in your app.


  <div id="app">
    <!-- Make sure to include this! -->
    <h1>My Page - Example</h1>
    <p>Normally people put some sort of Latin/hipster/bacon-related text here, but I wanted to try English instead, just to mix things up.</p>

export default {
  mounted() {
    // Send a notification after five seconds.
    setTimeout(() => {
      // Or whatever you use to send visual notifications.
      this.$someNotificationSystem.notify('A surprising announcement!');

      // Now send an auditory one.
      this.$announcer.set('Notification: A surprising announcement!')
    }, 5000)

Then just send a message using this.$announcer.set(MESSAGE).

Take a look at the repository for more up-to-date details. The people behind vue-announcer are just getting-started with their accessibility-related Vue projects, so watch that space!

  Tweet It

🕵 Search Results

🔎 Searching...