Custom Rulesets

This page is not available in the language you requested. You have been redirected to the English version of the page.
Link to this page copied to clipboard

Generate and apply custom rulesets for accessibility testing with Axe DevTools for Web CLI.

Not for use with personal data

The axe ruleset command generates JSON ruleset files that control which accessibility rules axe runs and how they behave. There are two workflows:

  • Standard guideline configs: Generate a pre-built config filtered to a specific accessibility standard (WCAG 2.2, Section 508, and so on).
  • Custom rulesets: Modify or extend existing axe-core rules (or define new ones) by describing your changes in a changes.json input file. The required filename changes.json is how axe ruleset locates your changes.

Both workflows produce an output JSON file. To apply it when scanning, pass it to the --custom flag of the scan command:

# Standard config workflow
axe ruleset --wcag22                          # generates wcag22.json
axe <url> --custom wcag22.json

# Custom ruleset workflow
axe ruleset --custom ./my-changes/            # reads changes.json from the directory, generates axe-ruleset.json
axe <url> --custom axe-ruleset.json

Standard Guideline Configs

These flags generate a JSON file pre-configured for a specific accessibility standard. The optional [filename] argument sets the output filename; if omitted, the file is named <standard>.json (for example, wcag22.json). Files are written to the current directory unless you specify a destination with -d, --destination.

Flag Standard
--508 [filename] Section 508
--en301549 [filename] EN 301 549
--ttv5 [filename] Trusted Tester v5
--rgaav4 [filename] RGAA Version 4
--wcag2 [filename] WCAG 2.0 Level AA
--wcag21 [filename] WCAG 2.1 Level AA
--wcag22 [filename] WCAG 2.2 Level AA
--wcag2aaa [filename] WCAG 2.0 Level AAA
--wcag21aaa [filename] WCAG 2.1 Level AAA
--wcag22aaa [filename] WCAG 2.2 Level AAA

Running axe ruleset with none of these flags generates individual config files for all supported standards at once.

--all [filename]

Generates a single JSON file containing all axe-core rules and checks, with every rule set to enabled: false. Use this as a starting point when you want an opt-in configuration. Every rule is off by default, and you enable only the rules you choose by modifying the file.

Standard Config Options

-d, --destination <path>

Output directory for the generated JSON file. Defaults to the current directory.

-f, --format [format]

Output format: json (default) or js.

-l, --log

Print a list of all rules included in the generated file to the console.

-a, --axe-source <path>

Path to a custom axe-core source file. Use this if you need to generate configs against a specific or patched version of axe-core.

Custom Rulesets

A custom ruleset lets you modify how existing axe-core rules behave or define new rules entirely. Changes are described in a changes.json file, which uses the same format as the object passed to axe.configure().

Some of the things you can do with custom rulesets include:

  • Change the impact level of a check's results (for example, demoting serious to minor)
  • Disable rules that don't apply to your context
  • Create new rules to enforce your organisation's accessibility policy
  • Restrict what techniques are accepted for a given requirement (for example, disallowing title as an accessible name for images)
  • Modify contrast thresholds in the color-contrast rule
  • Update which ARIA roles and properties are supported

Generating a Custom Ruleset

To generate a custom ruleset, create a changes.json file describing your changes, then run axe ruleset --custom <directory>, where <directory> is the folder containing your changes.json. If you omit --custom, the current directory is used.

The changes.json file can specify changes to existing axe-core rules and checks, as well as new rules or checks.

Note that impact is a property of checks, not rules. Although the generated axe-ruleset.json output shows an impact field on each rule, this is a resolved value computed from the rule's underlying checks; it is not something you set on a rule in changes.json. Placing impact directly on a rule in your input file will cause an error.

To change the perceived severity of a rule's findings, modify the impact on the underlying check. For example, to change the valid-lang check from serious to minor:

{
    "checks": [{
        "id": "valid-lang",
        "metadata": {
            "impact": "minor"
        }
    }]
}
important

The following is incorrect and will produce an error:

{
    "rules": [{
        "id": "valid-lang",
        "impact": "minor"
    }]
}

Save this as changes.json in a directory and run:

axe ruleset --custom ./my-changes/

Using Rules and Checks Directories

For more complex customizations, you can organize new rules and checks into separate rules/ and checks/ directories alongside changes.json. Each rule or check is its own JSON file. This doesn't change the generated output, but makes it easier to manage multiple custom rules and checks.

For example, to create a new rule called h1-no-duplicate that checks for more than one <h1> on a page:

directory
 ├ changes.json
 ├ rules
 │  └ h1-no-duplicate.json
 └ checks
    └ page-no-duplicate-h1.json

Because the rule and check are defined in separate files, changes.json is an empty object:

{}

The h1-no-duplicate.json rule file defines which checks to run:

{
    "id": "h1-no-duplicate",
    "selector": "h1:not([role]), [role=heading][aria-level=1]",
    "tags": ["cat.semantics", "best-practice"],
    "metadata": {
        "description": "Ensures the document has at most one h1 element",
        "help": "Document must not have more than one h1 element"
    },
    "all": [],
    "any": ["page-no-duplicate-h1"],
    "none": []
}

The page-no-duplicate-h1.json check file defines the check and its result messages:

{
    "id": "page-no-duplicate-h1",
    "evaluate": "page-no-duplicate-evaluate",
    "after": "page-no-duplicate-after",
    "options": {
        "selector": "h1:not([role]), [role=heading][aria-level=1]"
    },
    "metadata": {
        "impact": "moderate",
        "messages": {
            "pass": "Document does not have more than one h1 element",
            "fail": "Document has more than one h1 element"
        }
    }
}

The evaluate and after fields reference JavaScript function IDs that implement the check logic. For checks that modify an existing axe-core check, use the ID of an existing axe-core evaluate or after function. For entirely new checks, you must also register the corresponding JavaScript functions with axe-core. See the axe-core API documentation for details.

After running axe ruleset --custom, the generated JSON combines the rule and check definitions into a single file (relevant portion shown):

{
    "rules": [{
        "id": "h1-no-duplicate",
        "selector": "h1:not([role]), [role=heading][aria-level=1]",
        "tags": ["cat.semantics", "best-practice"],
        "metadata": {
            "description": "Ensures the document has at most one h1 element",
            "help": "Document must not have more than one h1 element"
        },
        "all": [],
        "any": ["page-no-duplicate-h1"],
        "none": [],
        "enabled": true
    }],
    "checks": [{
        "id": "page-no-duplicate-h1",
        "evaluate": "page-no-duplicate-evaluate",
        "after": "page-no-duplicate-after",
        "options": {
            "selector": "h1:not([role]), [role=heading][aria-level=1]"
        },
        "metadata": {
            "impact": "moderate",
            "messages": {
                "pass": "Document does not have more than one h1 element",
                "fail": "Document has more than one h1 element"
            }
        },
        "enabled": true
    }]
}

Custom Ruleset Options

-c, --custom [path]

Path to the directory containing your changes.json file (and optional rules/ and checks/ subdirectories). Defaults to the current directory.

-t, --tags <list>

Comma-separated list of axe-core tags used to filter which rules from the standard axe-core ruleset are included in the output.

-x, --disable-other-rules

Disables all axe-core rules not explicitly included in the rules property of changes.json or the rules/ directory. Enabled by default, so the generated ruleset replaces the full axe-core ruleset rather than extending it; only your custom rules run. Pass --no-disable-other-rules to include all standard axe-core rules alongside your custom ones.

--only-changes

Only valid with --custom. Generate only the changes and additions described in changes.json, without the full axe-core rule and check definitions. Produces a smaller file suitable for use as an overlay on top of an existing ruleset.

-d, --destination <path>, -f, --format, -l, --log, -a, --axe-source <path>

See Standard Config Options. These options apply to custom rulesets as well.

Loading a Ruleset

There are three ways to apply a generated ruleset when scanning. They are checked in this order:

  1. Environment variable: Set AXE_RULESET_PATH to the path of the ruleset file. This takes precedence over all other methods and applies to all runs in that environment.

  2. --custom flag: Pass the ruleset file explicitly using the --custom flag on axe <url>, axe spec, or axe bulk-spec.

  3. Local file: Place a file named axe-ruleset.json in the directory where axe runs. It will be used automatically if neither of the above are set.

If none of these are specified, or if Axe DevTools cannot load the specified file, the wcag2.1 default ruleset is used.

Support

Creating custom rulesets requires a significant understanding of axe-core. For details, see the axe-core API documentation. If you would like support on creating and maintaining your custom ruleset, contact your Deque representative.