Skip to content

Sa11y 5.0

Choose a tag to compare

@adamchaboryk adamchaboryk released this 17 Apr 01:47
· 11 commits to master since this release
fce9f64

This release features a significant refactor focused on XSS prevention, performance optimization, and reduced bundle size. The update enhances existing accessibility checks and includes a first-of-its-kind experimental Language Detection check, powered by the on-device Language Detector API (currently exclusive to Google Chrome).

New experimental checks for language detection

This new ruleset leverages on-device AI to automatically detect and validate the language of your content, ensuring it matches a web page’s language declaration. This feature helps identify issues pertaining to the following WCAG success criteria:

  • Language of Page (Level A): Verifies that the primary language declared in the document matches the actual content on the page.
  • Language of Parts (Level AA): Scans individual text blocks and image alt text to ensure shifts in language are correctly identified via the lang attribute.

Demo

Implementation notes

  • This is an experimental browser API and is only available in Chrome at this time.
  • For better performance, Sa11y will only run this check once on a page. It will stop scanning remaining element nodes after the first detection. If significant text changes are detected on the page, Sa11y will trigger a fresh scan.
  • This feature utilizes a built-in browser Language Detector API. All language analysis is performed locally on your machine, ensuring your page content is never sent to a cloud server or external third party for processing.

Disclaimer: Please note that AI-detection is not 100% accurate and is intended only to flag glaring issues for manual review; results should always be verified by a human.

Enabling this check

This experimental check is off by default. To start using these rules, update your configuration with the following properties:

  • langOfPartsPlugin: Set to true to activate the ruleset.
  • langOfPartsCache: Set to true to enable smarter caching. This prevents redundant scans by storing results for up to 200 URLs and only triggers a fresh analysis if it detects a change in page text, declared language, or previously flagged elements.

Ruleset & logic improvements

  • Page language attribute validation: New ruleset that validates language codes by leveraging the browser’s native Intl.DisplayNames API for improved accuracy over standard string matching. The logic detects and flags invalid declarations, such as those using underscores (e.g., en_US), and provides the normalized string as a recommended suggestion for the user to implement. To ensure stability across all environments, the check includes a regex-based fallback for legacy browsers. New test names include: META_LANG_VALID and META_LANG_SUGGEST.

  • New link checks: The LINK_UNPRONOUNCEABLE rule has been introduced as a standalone check to differentiate links containing only symbols (e.g., ., >, ?) from truly empty tags. This new rule provides a specific tooltip suggesting the link may be a copy-paste error and should either be deleted or given descriptive text. By separating this logic, the audit now offers clearer, more actionable feedback for non-alphanumeric content that screen readers cannot meaningfully process.

    • The LINK_MAYBE_BUTTON rule compliments the QA_IN_PAGE_LINK check to ensure that broken same page links which resemble a scripted UI control will receive a more appropriate error description.
    • Improved DOI detection: The LINK_DOI check has been improved to detect link text matching Digital Object Identifiers (DOIs) that lack a prefix. The updated regex identifies strings starting with 10.xxxx, ensuring that academic and technical references are properly captured even when formatted as plain text within a link.
  • Alt text quality checks: Improved detection of nonsensical alt text strings.

    • Added untitled image, unnamed, and copy to alt placeholder check for English language files.
    • When checking for placeholder stop words, special characters are filtered out to improve accuracy of check (in addition to numbers).
    • Alt text that have no spaces, are at least 15 characters, and contain at least 3 dashes/underscores will be flagged as an error.
    • New warning-level check that builds upon existing logic for identifying auto-generated alt text. This separate condition flags instances where there is a lower confidence that the text is machine-generated, but it still warrants a manual review. An image will now trigger a warning if its alt text meets any of the following:
      • Numeric strings: Consists of 5 or more digits (e.g., 12345).
      • Excessive delimiters: Contains more than 3 hyphens (-) or underscores (_).
  • Contrast module improvements:

    • Now supports the display-p3 color gamut.
    • Contrast logic for gradients has been refined; warnings are now only triggered if a specific color stop fails, significantly reducing false positives.
    • Transparent foreground colours and disabled elements are now ignored.
    • Performance has also been improved through optimizing the RGBA color conversion logic, reducing computational overhead. Addition of caching and memoization of various functions to prevent redundant DOM traversals for the same elements.
    • Added contrast checking support for slotted elements by traversing the flattened DOM tree to accurately detect background colours across Shadow DOM boundaries.
    • Contrast check will ignore nodes that only contain non-text characters or visual separators (like / or \ or |).
  • Minimized false positives:

    • Minor logic fixes to reduce false positives around fake heading detection.
    • Warnings for justified and small text can now be dismissed all.
    • Minimize false positives for test LABELS_ARIA_LABEL_INPUT.
    • Reduced false positives around fake list detection, and improved detection of potential fake list patterns.
  • Changes to “Good” annotations: The tooltip text for images and links flagged as "Good" will now display "Review" instead. While these elements may technically have alt text or accessible names, the quality of that content still requires human verification. This change prompts developers and authors to ensure the descriptions are actually meaningful, rather than just present.

  • Improved tooltip verbiage for LINK_IDENTICAL_NAME and QA_IN_PAGE_LINK

  • New test: TABLES_INVALID_HEADERS_REF evaluates whether the headers attribute within a table contains an invalid reference.

  • New test: ARIA_INPUT_FIELD_NAME evaluates ARIA-based input or switch fields for an accessible name.

Targeted element exclusion

Developers can now programmatically ignore elements by specific test keys. This provides more granular control, allowing you to exclude specific elements per check, without silencing all other accessibility alerts for that same item. Using the prop ignoreByTest.

For example:

ignoreByTest: {
  QA_FAKE_HEADING: 'p.ignore strong',
},

Security Improvements

  • XSS hardening: Mitigated cross-site scripting by replacing unsafe HTML parsing with secure DOM APIs and literal text rendering.
  • Improved data privacy: Hashing is used to hide the values used for dismiss keys, ensuring that data pulled from page elements remains private.
  • Code Quality: Integrated CodeQL analysis workflows and custom configuration files for automated security scanning.

Developer changes

Significant refactoring of the main Sa11y class now includes dedicated state management for better stability and cleaner code architecture.

  • Utility methods: All utility functions exposed are now exposed as methods for custom implementations.
  • Sanitization: Raw text strings passed via custom checks now receive automatic HTML sanitization. However, it’s highly recommended to always use Lang.sprintf() when passing in tooltip content for custom checks.
  • New prop: New prop paragraphIgnore: 'table p', to add exclusions for specific paragraph <p> elements.
  • Removed functions: Removed decodeHTML, escapeHTML, and stripHTMLtags. These utilities are now obsolete as Sa11y leverages native DOM APIs and literal text rendering for improved security.
  • Migration of tippy.js to floating-ui: Tippy.js was archived November 2024. Migration to floating-ui improves performance and reduces total bundle size by almost 10%.

Bug fixes

  • Added fallback for panelPosition prop to ensure proper visual placement of control panel.
  • Bug fix regarding altPlaceholder prop.
  • Adjusted readability thresholds and closed score gaps for more consistent analysis.
  • Improvements to accessible name calculation.
  • Console error message now includes Sa11y’s configuration to help debug.
  • Fixed a memory leak.
  • Fallback icon added to the Images panel when an image’s source is invalid, or an SVG, or is less than 1px in width or height.

Translations

New Tamil translation. Many thanks to Jayaseelan Samuel @smartsw33t!

Acknowledgments

Many thanks to @itmaybejj for his contributions to this release!