The plugin registers itself through the following hooks, no core template is overridden:
| Hook | Purpose |
|---|---|
sylius_shop.base#stylesheets |
Loads accessibility.css |
sylius_shop.base#javascripts |
Loads accessibility-early.js (synchronous, before the first paint) and accessibility.js |
sylius_shop.base.header |
The skip link (priority 1000, very first) and its target (priority 50) |
sylius_shop.base.offcanvas |
The floating widget itself, outside the page wrapper |
A theme that replaces those hook slots has to render the plugin's templates itself, or nothing appears.
The shop's base layout has no <main> and no content id. The plugin therefore prints an empty, focusable <div id="mmd-a11y-main" tabindex="-1" role="region"> between the navigation and the flash messages, so a validation error or "added to cart" message is not skipped after the jump. If your theme moves the content elsewhere, override templates/shop/skip_target.html.twig.
The effects are plain classes on <html>, colours/spacing can be overridden from your theme via CSS custom properties:
:root {
--mmd-a11y-primary: #0b6b3a;
--mmd-a11y-primary-dark: #08522c;
--mmd-a11y-offset-x: 24px;
--mmd-a11y-offset-bottom: 90px;
--mmd-a11y-z-index: 1020;
}
| Setting | Classes on <html> |
|---|---|
| Font size | mmd-a11y-font-small, mmd-a11y-font-large |
| Contrast | mmd-a11y-contrast-high, mmd-a11y-contrast-inverted |
| Colour filter | mmd-a11y-filter-protanopia, -deuteranopia, -tritanopia |
| Blue light | mmd-a11y-blue-light |
| Reduced motion | mmd-a11y-reduce-motion |
localStorage key: mmd-accessibility-settings. A headless storefront can reuse the same classes as a convention (see Shop API).
The colour filters deliberately sit on
<html>, not on a wrapper element: a filter on a wrapper would become the containing block of everyposition: fixedelement (sticky headers, banners) and break their placement.
<head> (accessibility-early.js, an external file so a strict CSP needs no exception for it) puts the saved choices on <html> before the first paint. The widget script builds on it.url('#id') in an external stylesheet cannot reach the inline SVG filters; a strict Content Security Policy therefore needs a nonce or hash for that <style>.asset(): while a Sylius theme is active it rewrites bundle assets to /_themes/..., which exist only after sylius:theme:assets:install. The file's modification time is the cache-busting version.