Getting Started with Web Accessibility in Vue

Emily Mears
9 min readJan 15, 2018


[I have re-published this on my personal blog!]

Vue is almost 4 years old, and has really shot up in popularity over the past year or so. With this growth, comes an increase in the number of Vue contributors, supporters and web applications. It’s important to know, at any stage, the best accessibility practices for Vue so that we don’t get a growth in inaccessible web applications.

I will be going over some accessibility concepts, fixes and implementations using Vue, and give some useful resources for those who are interested.

The Vue core team is yet to release their official accessibility guide, however there are a lot of articles, talks, repositories and demonstrations out there aiming to help developers overcome accessibility issues.

Most of the implementations I describe in this post rely on an understanding of the standard HTML features which are designed to improve the accessibility of a web page, as well as the ability of assistive technologies to interpret a web page.

If you are new to the idea of web accessibility, I have written two other blog posts: Getting Started with Web Accessibility, and Getting Started with Web Accessibility in React.

How does Vue work?

When a browser parses an HTML document, it will create a Document Object Model (DOM) to represent the document as a collection of Nodes and Objects, like a tree.

The DOM is essentially just an object-oriented representation of all the items in a web page, encapsulating all of the methods and properties available for each of them in an object. The document is itself an object. — [3]


When you use JavaScript, or tools like jQuery, you will be interacting with the DOM to grab, modify or insert elements. The browser will need to find the required DOM nodes and make the changes. There can be thousands of DOM nodes, and so updates can be very expensive. [4]


Like React, Vue 2.0 uses a Virtual DOM to accelerate DOM updates. This provides performance improvements, by preventing a lot of work as it is much less expensive to update virtual nodes. This is because updating a JavaScript object is faster than directly calling the DOM API. [5]


A Virtual DOM is simply a ‘virtual’ representation of the DOM. For every DOM object, there will be a corresponding object in the Virtual DOM.

Example of the Traditional DOM node representation:

Virtual DOM node representation:

Unlike React, Vue tracks component dependencies during its render, so on state change, only the components which needed to be re-rendered actually are. This prevents re-rendering child components unnecessarily.

In React, when a component’s state changes, it triggers the re-render of the entire component sub-tree, starting at that component as root. — [6]

When creating a Vue web application, you start by creating a Vue instance. You use the Vue function to do this in the following way, passing in an options object:

var vm = new Vue({
// options

Every Vue component is also a Vue instance, and so they (almost) all accept the same options object. [1] After the creation of your Vue instance, all of the properties found in the instance’s data object are added to the reactivity system. This essentially means that the view layer of your application will update when changes in data are detected.

DOM updates are performed asynchronously, where all changes in the same event loop are queued. In the next loop, the changes will be made. [2]

Every Vue component you have defined has an assigned watcher instance. This watcher will know which properties of your component it should take note of which properties it should watch, and then will be notified when that property is modified, and will trigger a re-render.


Vue components are very powerful in that they allow developers to create elements which are reusable. Components can either be defined globally, and be accessible throughout your application, or locally, where it is usable only in the scope of a certain Vue component.

Each Vue instance has a series of initialisation steps, as well as lifecycle hooks which are called throughout its lifetime. The diagram below explains the instance lifecycle:


Understanding how Vue apps are created, structured and updated is important to help understand how web accessibility features in Vue may work, and how you can modify them. It’s also interesting which is a bonus. 💪🏽

Getting Started with Accessibility in Vue

I’ll go through a few different ways you can improve the accessibility of your Vue application, with some examples. I will be providing some resources at the end of this post as well if you are particularly interested!

Managing Focus

Keyboard focus and navigation is extremely important when developing for the accessible web. If a user cannot use other input mechanisms, they will have an extremely hard time interacting and navigating your site.

Accessible websites enable people to access all content and functionality — links, forms, media controls, etc. — through a keyboard.

Web applications can easily introduce issues for these users by:

  • Removing visual indicators of which element is currently in focus.
  • Modifying the tabindex , or generating badly structured HTML.

By default, users can only navigate to links, buttons, and form controls with a keyboard. [10] You should use these elements as much as possible, and if not possible you should be sure to use tabindex = 0 to ensure it is keyboard accessible.

The focused element is the one which is currently receiving keyboard input. A common example is the blue outline which is added to buttons when they are in focus. It is important not to remove this indicator by using CSS such as outline: 0 or outline: none .

In the second image, the keyboard focus is on the ‘Search Twitter’ input, as we can see by the green(ish) outline.

Whilst a user is interacting with your web application, Vue will be making a lot of modifications to the DOM in the background. This can result in the user’s focus being thrown around, and ultimately can make the experience very frustrating and disorienting.

Vue allows developers to create custom directives, which can help with focusing form elements. [11] The example of how to give automatic focus to a form element, for example, is given in the Vue documentation:

There is also vue-focus which has a similar outcome- this can be used for managing focus when modals are introduced, or ensuring that users can move between form fields or elements using cursor keys, for example.

Another method of handling focus within your web application is through using global event handling. If you use vue-global-events , you will get access to the GlobalEvents component which gives you the ability to listen to global events.

You can then register global events in a component in your template, and define how your application responds to them [13]:

These methods offer solutions for a lot of keyboard access issues, however it’s important not to overuse solutions which alter the core experience for users, to avoid confusion. It is also important that you first focus (😏) on creating understandable components, which generate semantically-correct HTML.


ARIA (Accessible Rich Internet Applications) are a core part of simple accessible web development. It works by letting the developer specify attributes that change the way an element is translated into the accessibility tree. [14]

Although ARIA lets us specify attributes, it does not make an element focusable or give it any keyboard event listeners, so that is something that still needs to be done by the developer.

ARIA is a set of attributes defining ways to make web applications more accessible for users with disabilities.

ARIA is very important for when you are creating custom elements, or modifying standard HTML elements. A good example would be [14]:

While this works fine for sighted users, a screen reader will give no indication that the element is meant to be a checkbox, so low-vision users may miss the element entirely. — [14]

We can add missing attributes to our fake checkbox element using an ARIA role and aria-checked attribute. This will identify the element as a checkbox to users using screen readers:

There are many different roles, and ARIA attributes, generally, and they are extremely important to be aware of when developing any web application, using any web framework.

ARIA attributes can be used with Vue components easily- you can add them the same way you would in standard HTML. You can also bind the value of an ARIA attribute to component data:

ARIA roles and landmarks can also be used to section out parts, or landmarks, of your page. This allows for skip links to be used, allowing keyboard users to skip to certain parts of your page.

Bootstrap-Vue is an awesome CSS/Component library with a lot of ready-made Vue components, complete with extensive ARIA coverage, and they actively improve on the accessibility of their components.

Setting the Title

Dynamically setting the title of a webpage is important for a number of reasons. Those people seasoned in the art of SEO (Search Engine Optimisation) will know that having relevant titles for each page of a website is hugely important.

In terms of web accessibility, titles are often the first thing that is read to users relying on screen reading technology [7]. Having the same title for every part of your web application would be extremely confusing for those users.

Good page titles are particularly important for orientation — to help people know where they are and move between pages open in their browser. The first thing screen readers say when the user goes to a different web page is the page title. — [7]

Vue tries to stay away from modifying page metadata, the <head> and <body> elements, as much as possible. A common issue is when using vue-router , and you want to dynamically alter the page title conditionally- depending on the component which is rendered.

Packages such as vue-head and vue-meta have been made by members of the Vue community, adding the ability to add metadata when instantiating a component.

To dynamically modify the title, you can add metadata when you declare a route. The following example assumes you have a Home Page for your application, and a Contact Us page containing contact details for the company:

You can then use the beforeEach hook provided by vue-router . This hook is called in creation order, whenever a navigation is triggered. It takes three arguments:

  • to — This is the route object being directed to.
  • from — This is the source route (the one being navigated away from.
  • next — This is a function which resolves the hook when called. This must be called or else the route will never be resolved.

You can take this further and update more page metadata using a similar method, and this is written about by Joshua Bemenderfer on

I am planning to add more to this in the future, and will be adding resources as I find them. In the meantime, I hope this is a helpful introduction to the world of accessibility in Vue.js!


[1] — The Vue Instance

[2] — Reactivity in Depth

[3] — Getting Started with Web Accessibility in React

[4] — What’s New in Vue.js 2?- Virtual DOM

[5] — What’s the Deal with Vue’s Virtual DOM?

[6] — Comparison with Other Frameworks

[7] — Easy Checks -A First Review of Web Accessibility

[8] — Updating Page Title & Metadata with Vue.js & vue-router

[9] — Global Guards

[10] — WebAIM: Keyboard Accessibility

[11] — Custom Directives

[12] — vue-focus

[13] — Handle Global Events in Vue.js

[14] — Introduction to ARIA



Emily Mears

computer science student at ucl, feminist, cheese fan, vue / react, looking forward to the future 🌏

Recommended from Medium


See more recommendations