Skip to content

Theme And Developer Integration

Open Accessibility exposes a shared targeting layer plus filters for widget presentation. The goal is simple: let the plugin work across more WordPress themes without writing theme-specific hacks into the plugin itself.

The targeting layer arrived in 1.3.02. The presentation and skip-target filters described under Widget Presentation Filters were added in 1.4.0.

How Targeting Works

The frontend receives a normalized target configuration from PHP. JavaScript resolves those selectors into current DOM elements, excludes known unsafe areas, then applies feature controls to the resolved targets.

The main target groups are:

  • roots: content regions where controls are allowed to operate.
  • readable_text: paragraphs, lists, blockquotes, captions, table cells, labels, and similar text.
  • headings: heading elements.
  • links: links inside allowed roots.
  • media: media elements for image and visual controls.
  • interactive: links, buttons, inputs, selects, textareas, summaries, and tabindex-enabled controls.
  • layout_containers: opt-in containers eligible for layout relief.
  • excluded: theme areas that should not be changed by target mutations.

PHP Filters

Use these filters when a theme needs global behavior.

Add A Content Root

add_filter( 'open_accessibility_target_roots', function( $roots ) {
	$roots[] = '.my-theme-article-body';

	return $roots;
} );

Exclude A Theme Region

add_filter( 'open_accessibility_target_excluded_selectors', function( $selectors ) {
	$selectors[] = '.my-theme-sidebar';
	$selectors[] = '.promo-card';

	return $selectors;
} );

Add Layout Relief Targets

Use layout relief for containers that may clip larger text because of fixed height, overflow, or line clamping.

add_filter( 'open_accessibility_layout_relief_selectors', function( $selectors ) {
	$selectors[] = '.my-theme-fixed-story-card';

	return $selectors;
} );

Refine A Target Group

add_filter( 'open_accessibility_target_group_selectors', function( $selectors, $group_name ) {
	if ( 'readable_text' === $group_name ) {
		$selectors[] = '.my-theme-readable-copy';
	}

	return $selectors;
}, 10, 2 );

Take Complete Control

open_accessibility_target_config receives the final full targeting array before it is sent to the browser.

add_filter( 'open_accessibility_target_config', function( $config ) {
	$config['roots'] = array( '.site-main-content' );
	$config['groups']['readable_text'] = array( '.entry-copy', '.article-summary' );
	$config['groups']['headings'] = array( '.entry-title', '.entry-copy h2' );
	$config['excluded'][] = '.site-navigation';

	return $config;
} );

Returning an empty selector array intentionally disables that default selector set:

add_filter( 'open_accessibility_target_config', function( $config ) {
	$config['groups']['media'] = array();

	return $config;
} );

If roots is empty, Open Accessibility does not fall back to document.body. A template can still opt a region back in with data-oa-root.

Widget Presentation Filters

These filters were added in 1.4.0 and control what the widget says and links to, rather than where controls apply.

Override Any Widget String

open_accessibility_strings receives the full array of widget labels.

add_filter( 'open_accessibility_strings', function( $strings ) {
	$strings['reading_mask'] = __( 'Focus band', 'my-theme' );

	return $strings;
} );

Change The Panel Title

The Panel Title setting covers most cases. Use the filter when the title needs to vary by context.

add_filter( 'open_accessibility_panel_title', function( $title ) {
	if ( is_singular( 'product' ) ) {
		return __( 'Product accessibility tools', 'my-theme' );
	}

	return $title;
} );

The Links settings tab populates Help, Feedback, Sitemap, and Statement links. Filter the resolved list to add, remove, or reorder them.

add_filter( 'open_accessibility_panel_links', function( $links ) {
	$links[] = array(
		'url'   => home_url( '/accessibility-contact/' ),
		'label' => __( 'Contact the accessibility team', 'my-theme' ),
	);

	return $links;
} );

Control Where Skip-To-Content Lands

As of 1.4.0 the skip link resolves a real target even on themes without an #content element, and moves keyboard focus to it. Use this filter to control the candidate list.

add_filter( 'open_accessibility_skip_target_candidates', function( $candidates ) {
	array_unshift( $candidates, '#primary-article' );

	return $candidates;
} );

Candidates are tried in order, and the first one present in the document wins.

HTML Attributes

Use HTML attributes for one-off template cases.

Add A Root

<main data-oa-root>
	...
</main>

Add An Element To Target Groups

<article data-oa-target="readable_text headings">
	<h2>Story title</h2>
	<p>Readable story text.</p>
</article>

Ignore A Region

<aside data-oa-ignore>
	This region will not be modified by Open Accessibility target mutations.
</aside>

The class alias also works:

<div class="open-accessibility-ignore">
	Do not modify this region.
</div>

data-oa-ignore and .open-accessibility-ignore are built-in safety exclusions. They continue to work even if configurable exclusions are emptied.

Opt Into Layout Relief

<div class="story-card" data-oa-relax-layout>
	<p>Text that may grow when a visitor increases text size.</p>
</div>

Preserve A Layout

<div data-oa-preserve-layout>
	This region will stay out of layout relief.
</div>

JavaScript API

Open Accessibility exposes window.OpenAccessibility after the widget initializes.

window.OpenAccessibility.refresh();
window.OpenAccessibility.getState();
window.OpenAccessibility.setState({ textSize: 2 });
window.OpenAccessibility.getTargets('readable_text');
window.OpenAccessibility.debug();

Refresh After Dynamic Rendering

Use refresh() after AJAX, sliders, faceted search, or other frontend rendering changes.

document.addEventListener('myTheme:cardsRendered', function() {
	window.OpenAccessibility.refresh();
});

Inspect Targets

const readableTargets = window.OpenAccessibility.getTargets('readable_text');
const diagnostics = window.OpenAccessibility.debug();

debug() returns current state and target counts, including invalid selectors.

Apply State

window.OpenAccessibility.setState({
	textSize: 2,
	lineHeightLevel: 1,
	linksUnderline: true
});

The public state setter normalizes supported values before applying them. Malformed enum values are reset to safe defaults, and numeric levels are clamped to supported ranges.

Lifecycle Events

The plugin dispatches lifecycle events on document:

  • openAccessibility:ready
  • openAccessibility:targetsRefreshed
  • openAccessibility:beforeApply
  • openAccessibility:afterApply
  • openAccessibility:reset

Example:

document.addEventListener('openAccessibility:afterApply', function(event) {
	console.log(event.detail.state);
	console.log(event.detail.targets);
});

Browser Diagnostics

Enable browser-side diagnostics while testing:

localStorage.setItem('openAccessibilityDebug', '1');
location.reload();

Then inspect:

window.OpenAccessibility.debug();

Turn diagnostics back off:

localStorage.removeItem('openAccessibilityDebug');
location.reload();

Testing Checklist For Theme Integrations

After adding integration rules, test:

  • Home page.
  • Single post or article page.
  • Archive or category page.
  • Mobile viewport.
  • Text size increase and reset.
  • Line height increase and reset.
  • Link underlining.
  • Hide images.
  • Reading guide.
  • Reading mask.
  • Skip to content, including keyboard focus landing on the intended target.
  • Each contrast mode, confirming the widget itself stays reachable.
  • Widget open, close, Escape key, and focus return.

Watch navigation, sidebars, ad containers, code blocks, and fixed-height cards. These are the most common places where whole-page accessibility controls can get spicy.