Accessibility core
Use these rules to check the basic accessibility information in a Vue template: image alternatives, link text, valid ARIA attributes, keyboard equivalents, and form labels. Start here when adding images, links, or inputs to a component.
For example, open form-control-has-label before adding
an input: compare its Bad/Good examples, enable the rule with the shown Vite+ configuration, and
run vp run lint. The complete accessibility guide explains the broader rule set.
Every rule on this page includes its purpose, prerequisites, configuration, and complete Bad/Good examples. Highlighted lines show the changes; copied code keeps the complete source. Each packet states its current support limits.
| Rule | Examples | Purpose |
|---|---|---|
a11y/alt-text |
Bad · Good | Require alternative text for media elements |
a11y/anchor-has-content |
Bad · Good | Require anchor elements to have accessible content |
a11y/anchor-is-valid |
Bad · Good | Enforce valid href on anchor elements |
a11y/aria-props |
Bad · Good | Disallow invalid ARIA attributes |
a11y/aria-role |
Bad · Good | Elements with ARIA roles must use a valid, non-abstract ARIA role |
a11y/aria-unsupported-elements |
Bad · Good | Disallow ARIA attributes on elements that do not support them |
a11y/click-events-have-key-events |
Bad · Good | Require keyboard event handlers with click events |
a11y/form-control-has-label |
Bad · Good | Require form controls to have associated labels |
All rules · Rule Options · ESLint migration map · Project checks · Attributes across components
a11y/alt-text
Require alternative text for media elements
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"a11y/alt-text": "warn"
}
},
},
});
vp run lint
Bad
The image submit control supplies only its image URL; it has no alt text describing the action.
<template>
<input type="image" src="/submit.png" />
</template>
Good
alt="Submit search" gives the image control an accessible name that describes submitting the search.
<template>
<input type="image" src="/submit.png" alt="Submit search" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/anchor-has-content
Require anchor elements to have accessible content
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"a11y/anchor-has-content": "warn"
}
},
},
});
vp run lint
Bad
The /settings link has no text or other naming content, so its destination has no accessible description.
<template>
<a href="/settings"></a>
</template>
Good
The visible Settings text supplies content for the same destination link.
<template>
<a href="/settings">Settings</a>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/anchor-is-valid
Enforce valid href on anchor elements
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"a11y/anchor-is-valid": "warn"
}
},
},
});
vp run lint
Bad
The first anchor uses # for an action; the second uses a JavaScript URL. Neither provides an ordinary navigation destination.
<template>
<a href="#" @click="openPanel">Open panel</a>
<a href="JaVaScRiPt:void(0)">Run action</a>
</template>
Good
A native button performs openPanel, while the remaining anchor has the real /docs/javascript-urls destination.
<template>
<button type="button" @click="openPanel">Open panel</button>
<a href="/docs/javascript-urls">JavaScript URL guide</a>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/aria-props
Disallow invalid ARIA attributes
Default severity: error
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"a11y/aria-props": "error"
}
},
},
});
vp run lint
Bad
aria-lable is misspelled and is not a supported ARIA attribute.
<template>
<button aria-lable="Save changes">Save</button>
</template>
Good
The supported aria-label attribute supplies the button name.
<template>
<button aria-label="Save changes">Save</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/aria-role
Elements with ARIA roles must use a valid, non-abstract ARIA role
Default severity: error
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"a11y/aria-role": "error"
}
},
},
});
vp run lint
Bad
datepicker is not a recognized ARIA role for this section.
<template>
<section role="datepicker">...</section>
</template>
Good
The section uses the recognized dialog role and a label describing the date selection.
<template>
<section role="dialog" aria-label="Choose a date">...</section>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/aria-unsupported-elements
Disallow ARIA attributes on elements that do not support them
Default severity: error
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"a11y/aria-unsupported-elements": "error"
}
},
},
});
vp run lint
Bad
The metadata element carries aria-hidden, although meta does not support ARIA attributes.
<template>
<meta charset="utf-8" aria-hidden="true" />
</template>
Good
Removing the ARIA attribute leaves the charset declaration intact.
<template>
<meta charset="utf-8" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/click-events-have-key-events
Require keyboard event handlers with click events
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Checks non-interactive elements without an interactive role. Native buttons and elements with an interactive ARIA role are outside this rule's finding.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"a11y/click-events-have-key-events": "warn"
}
},
},
});
vp run lint
Bad
The non-interactive div has a click handler but no keyboard event handling.
<template>
<div @click="activate">Activate</div>
</template>
Good
A native button provides keyboard activation for the same activate handler.
<template>
<button @click="activate">Activate</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/form-control-has-label
Require form controls to have associated labels
Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.
Configuration (Vite+)
import { defineConfig } from "@vizejs/vite-plugin/vite-plus";
export default defineConfig({
lint: {
vize: {
"preset": "incremental",
"rules": {
"a11y/form-control-has-label": "warn"
}
},
},
});
vp run lint
Bad
The search input has no label identifying what the user should enter.
<template>
<input type="search" />
</template>
Good
Wrapping the input in a label associates the visible Search text with the control.
<template>
<label>
Search
<input type="search" />
</label>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.