Getting Started
@k9n/eslint-plugin-prefer-implicit is an ESLint plugin that enforces implicit HTML semantics over explicit ARIA attributes and roles.
If the browser already knows it, don't repeat it.
See the plugin in action — violations are detected and fixed step by step:
Loading demo…
Motivation
Modern HTML already provides rich, implicit semantics. However, many codebases add redundant or even harmful ARIA attributes and roles. This plugin helps you:
- Reduce unnecessary ARIA usage
- Remove redundant or conflicting roles
- Encourage native HTML semantics
- Prevent accessibility regressions caused by overengineering
Installation
npm install --save-dev @k9n/eslint-plugin-prefer-implicit
info
This plugin requires ESLint ^10.0.0 with flat config.
Quick Setup
Use the recommended config to enable all six rules at "warn" severity:
- ESM (import)
- CommonJS (require)
eslint.config.js
import preferImplicit from "@k9n/eslint-plugin-prefer-implicit";
export default [preferImplicit.configs.recommended];
eslint.config.js
const preferImplicit = require("@k9n/eslint-plugin-prefer-implicit");
module.exports = [preferImplicit.default.configs.recommended];
That's it! See Configuration for more options.
Rules Overview
| Rule | Description | Fixable |
|---|---|---|
| no-redundant-role | Disallow role attributes that match the element's implicit ARIA role | ✅ |
| no-destructive-role | Disallow role attributes that remove native semantics of interactive or structural elements | ✅ |
| no-conflicting-aria | Disallow aria-live values that conflict with the implicit live region behavior of a declared role | ✅ |
| no-unsupported-aria | Disallow ARIA attributes not supported by the element's role | ✅ |
| no-default-aria | Disallow ARIA attributes set to their default value or empty string | ✅ |
| no-hidden-focusable | Disallow elements that are both focusable and aria-hidden="true" | ✅ |
Core Philosophy
- ✅ Native HTML first
- ✅ Implicit semantics over explicit declarations
- ✅ Conservative autofix (only when 100% safe)
- ❌ No guessing developer intent
- ❌ No breaking dynamic behavior