Getting started
Learn the basics of using Accented in your web application.
First steps
To try Accented without installing it, head over to the playground.
Install
You have two main options for installing Accented.
- As an NPM module (if you’re using a bundler).
- From an ES module registry (no build step required).
NPM:
Install via NPM (or with a different package manager like PNPM or Yarn).
npm install --save-dev accented
Then import the package.
import { accented } from 'accented';
ES module registry:
If you prefer to load Accented without a build step, consider using esm.sh as a CDN:
import { accented } from 'https://esm.sh/accented';
Run in development mode
Only run Accented in development.
It’s not a great idea to have Accented running in production:
- Accessibility issues should be surfaced to you — not your users.
- Accented’s browser support policy might differ from your app’s, and that may cause errors for some of your users on older browsers.
Depending on your setup, checking whether the code is running in development or in production may look differently.
Additionally, consider importing Accented dynamically, to ensure that its code is not included in the production bundle.
Starter code
You can use the following code as a starting point.
Run this on the client only — Accented doesn’t do anything server-side.
if (import.meta.env.MODE === 'development') {
const { accented } = await import('accented');
accented();
}
Run once per page
Accented should only be initialized once per page.
It uses axe.run()
under the hood,
which throws an error if called multiple times simultaneously.
If there’s a chance accented()
could be called more than once
(for example, in a component by a framework that supports hot reloading),
make sure to disable Accented when the component is unmounted.
/* Initialize on component mount */
const disable = accented();
...
/* Disable on component unmount */
disable();
Using in large projects
Introducing Accented to a large codebase may present an organizational challenge.
Similar to introducing linting, if you call accented()
with no options,
the output may be overwhelming, with dozens of issues reported per page.
To avoid this, introduce Accented gradually, with a combination of the following:
- Use the
context
option to limit scans to certain parts of the page. For example, you can start by scanning only certain components, and then gradually expand the context to include more components. - Use the
axeOptions
option to include or exclude some axe rules. Helpful if your app has lots of the same type of issue. By initially excluding the rule for that issue, you can make the output more manageable.
In the future, Accented may have a console-only mode (see issue #28), which would also make it easier to introduce Accented. If that sounds useful, consider upvoting the issue.
Using with frameworks (React, Vue, Angular, Svelte, etc.)
Accented is fully framework-agnostic. It uses a mutation observer to detect changes in the DOM, and it doesn’t matter what causes those changes or how your application’s codebase is structured.
That said, when using a framework, you have options:
- Call once during initialization (the simple option).
Just call
accented()
during client-side initialization — that’s it. - Create a reusable component. Consider it if you need to scan different parts on different pages. Here’s what such a component may look like in React:
import { accented } from 'accented';
import { useEffect, useRef } from 'react';
// This component should only be used once per page.
export function Accented({ children }) {
const containerRef = useRef(null);
useEffect(() => {
if (!containerRef.current) {
/**
* containerRef.current will be null in production,
* based on what this component returns.
*/
return;
}
const disable = accented({
// Initialize Accented only for the descendants of this element.
context: containerRef.current,
});
return () => {
/**
* Be sure to clean up on unmount.
* Without this, Accented could be initialized multiple times,
* which may lead to unpredictable behavior.
* See https://accented.dev/getting-started#run-once-per-page
*/
disable();
};
}, []);
/**
* How `isDevelopment` is calculated depends on your setup.
* See https://accented.dev/getting-started#run-in-development-mode
*/
if (isDevelopment) {
return (
<div ref={containerRef}>
{children}
</div>
);
}
return children;
}
Using in CI (continuous integration)
Accented is only meant for local development. It runs accessibility tests on the page that’s currently in the developer’s browser.
However, if you additionally need something similar for CI, consider using axe-core in your test suite — either directly or through wrappers such as jest-axe or axe-playwright (depending on your test framework).
Improving performance
Accented may negatively affect the performance of your application in development, however there are ways to reduce the performance impact.
Confirm that the issues are caused by Accented
The following may indicate that Accented takes too long to run:
- The page becomes slower to respond to user input.
- Animations become choppy.
To verify that the cause of these issues is indeed Accented,
and not something else in your application,
you can use the callback
option:
accented({
callback: ({ performance }) => {
const { totalBlockingTime, scan, domUpdate } = performance;
console.log(
`Accented run took ${totalBlockingTime}ms (scan: ${scan}ms, DOM update: ${domUpdate}ms)`
);
},
});
If totalBlockingTime
is low (less than 100 ms),
then Accented is probably not the cause of the performance issues.
If it’s high (a few hundred milliseconds),
try adjusting the run frequency (using throttle
)
or disabling some axe rules (using axeOptions
).
Change run frequency
Use the throttle
option
to control the minimal timeout between consecutive scans
and whether there should be a timeout between a mutation and a scan.
For example, if your page has lots of elements, and user interactions are followed by JS-driven animations, consider offsetting the scan by the duration of the animation:
accented({
throttle: {
wait: 500, // wait 500 ms to let animations finish
leading: false // don’t run the scan immediately after a mutation
}
});
You can tweak wait
and leading
values to find the right balance
between Accented responsiveness and app performance.
Disable some axe rules
If you find that even with a high wait
value,
Accented still takes too long to run,
consider disabling some axe rules.
This makes sense if you don’t expect certain types of issues.
For example, if you know you have a color scheme with high enough contrast,
you may get a noticeable performance boost by disabling the color-contrast
rule
which is expensive to test for:
accented({
axeOptions: {
rules: {
'color-contrast': { enabled: false }
}
}
});
See axeOptions
documentation for more details.
Styling
You can change some styling aspects of the elements that are added by Accented. It’s usually desirable to make such elements stand out on the page, so styles are worth adjusting if the Accented elements don’t stand out enough in your app.
You can make the changes by setting certain CSS properties in your app, for example:
:root {
--accented-primary-color: darkgreen;
--accented-outline-width: 3px;
--accented-outline-style: dashed;
}
Here’s what the updated styles would look like compared to the defaults:


See full CSS API in the Styling section of the API docs.
Using Accented with iframes
Accented doesn’t scan iframe contents.
If you wish to scan the document that’s rendered inside an iframe, and you have control over that document, initialize Accented in that document.
There will be no interference between the instances of Accented running in the parent and child documents.
If you don’t control the iframe’s content, you can’t run Accented there — and even if you could, it wouldn’t be useful, since you wouldn’t be able to fix the issues it finds.