Accessibility integrity
Use these rules when a template's roles, focus order, labels, or element relationships disagree. They help review the consistency of markup after adding ARIA roles or changing an interactive component.
For example, role-has-required-aria-props shows
which change to make when an assigned role is missing a required property. Compare the examples,
use that rule's configuration, then run vp run lint.
The complete accessibility guide links the other checks.
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/no-role-presentation-on-focusable |
Bad · Good | Disallow role="presentation" or role="none" on focusable elements |
a11y/no-static-element-interactions |
Bad · Good | Disallow event handlers on static elements |
a11y/placeholder-label-option |
Bad · Good | Require disabled or hidden on select placeholder option |
a11y/role-has-required-aria-props |
Bad · Good | Require ARIA roles to have required properties |
a11y/tabindex-no-positive |
Bad · Good | Disallow positive tabindex values |
a11y/use-list |
Bad · Good | Suggest using list elements for bullet-like text |
vue/use-unique-element-ids |
Bad · Good | Enforce unique element IDs using useId() instead of static literals |
All rules · Rule Options · ESLint migration map · Project checks · Attributes across components
a11y/no-role-presentation-on-focusable
Disallow role="presentation" or role="none" on focusable elements
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/no-role-presentation-on-focusable": "error"
}
},
},
});
vp run lint
Bad
The focusable billing link requests role=presentation, which conflicts with its interactive link role; browsers must ignore that presentation request.
<template>
<a href="/billing" role="presentation">Billing</a>
</template>
Good
Remove the conflicting presentation request and rely on the native link role and billing destination.
<template>
<a href="/billing">Billing</a>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/no-static-element-interactions
Disallow event handlers on static 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/no-static-element-interactions": "warn"
}
},
},
});
vp run lint
Bad
A static section receives an Enter-key action without an interactive role.
<template>
<section @keydown.enter="select">Select</section>
</template>
Good
A native button carries the same action with an appropriate interactive element.
<template>
<button type="button" @keydown.enter="select">Select</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/placeholder-label-option
Require disabled or hidden on select placeholder option
Default severity: warning
Presets: nuxt, 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/placeholder-label-option": "warn"
}
},
},
});
vp run lint
Bad
The empty-value prompt remains selectable as if it were a country value.
<template>
<select v-model="country">
<option value="">Choose a country</option>
<option value="jp">Japan</option>
</select>
</template>
Good
Adding disabled distinguishes the prompt from the selectable Japan option.
<template>
<select v-model="country">
<option value="" disabled>Choose a country</option>
<option value="jp">Japan</option>
</select>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/role-has-required-aria-props
Require ARIA roles to have required properties
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/role-has-required-aria-props": "warn"
}
},
},
});
vp run lint
Bad
The checkbox role omits aria-checked, which conveys the checkbox state.
<template>
<span role="checkbox">Receive updates</span>
</template>
Good
aria-checked="false" supplies the state required by the checkbox role.
<template>
<span role="checkbox" aria-checked="false">Receive updates</span>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/tabindex-no-positive
Disallow positive tabindex values
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/tabindex-no-positive": "warn"
}
},
},
});
vp run lint
Bad
A positive tabindex of 3 creates a custom focus order ahead of ordinary controls.
<template>
<button tabindex="3">Save</button>
</template>
Good
The button uses its native focus order without a positive tabindex.
<template>
<button>Save</button>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
a11y/use-list
Suggest using list elements for bullet-like text
Default severity: warning
Presets: nuxt, 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/use-list": "warn"
}
},
},
});
vp run lint
Bad
The task items are separate paragraphs with typed dash markers rather than list elements.
<template>
<p>- First task</p>
<p>- Second task</p>
</template>
Good
An unordered list and list items express the same tasks with list semantics.
<template>
<ul>
<li>First task</li>
<li>Second task</li>
</ul>
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.
vue/use-unique-element-ids
Enforce unique element IDs using useId() instead of static literals
Default severity: warning
Presets: nuxt, 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": {
"vue/use-unique-element-ids": "warn"
}
},
},
});
vp run lint
Bad
The literal email ID is reused by every instance of this component, which can misdirect its label when several instances are rendered.
<template>
<label for="email">Email</label>
<input id="email" />
</template>
Good
useId() produces the instance's emailId; bind the same value to the label's for and the input's id.
<script setup>
import { useId } from "vue";
const emailId = useId();
</script>
<template>
<label :for="emailId">Email</label>
<input :id="emailId" />
</template>
Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.