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.

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.

Bundler / framework
Import
Source
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:

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:

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:

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:

Screenshot of a web application, with highlights by Accented, having regular styles.Screenshot of the same web application, also with highlights by Accented. The highlights are dark green instead of violet red, and the outlines are dashed instead of solid.

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.