Skip to content
NewBun 1.4.5 is out. Release notes
AphrodyBun

Linter · Rules

jsx-a11y/anchor-is-valid

Require links to have a real href, and buttons to be button elements

You can't reach an a without an href with the Tab key, and it isn't announced as a link. An a with href="#" or href="javascript:..." and an onClick is announced as a link but acts like a button. Space doesn't press it, and "open in new tab" leads nowhere.

Use a with a real address to go somewhere. Use button to do something.

  • An href is missing if it has no value, or is null or undefined.
  • An href is invalid if it's "" or "#", or starts with javascript:.
  • A link with spread props and no href isn't reported, because the href might be in the spread.

Configure

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"jsx-a11y/anchor-is-valid" = "error" # or "warn"

Every option, set to its default. The ones that are commented out are unset by default.

bunfig.toml
[lint.rules]
"jsx-a11y/anchor-is-valid" = ["error", {
  components = [], # list of strings
  specialLink = [], # list of strings
  # aspects = <list of strings>,
}]

Examples

Reported:

const home = <a>Home</a>;
const top = <a href="#">Back to top</a>;
const save = <a href="#" onClick={saveDraft}>Save</a>;

Not reported:

const home = <a href="/">Home</a>;
const top = <a href="#top">Back to top</a>;
const save = <button onClick={saveDraft}>Save</button>;
const tracked = <a href="/pricing" onClick={trackClick}>Pricing</a>;
const docs = <a {...linkProps}>Docs</a>;

Options

OptionDefaultWhat it does
components[]Components to check like a.
specialLink[]Other attributes that count as href.
aspectsall threeWhich checks run: "noHref" (no href), "invalidHref" (an href that goes nowhere), "preferButton" (an onClick with a missing or invalid href).
const home = <Link>Home</Link>;
const home = <Link to="/">Home</Link>;

With only "invalidHref", a link without an href is allowed:

const home = <a>Home</a>;