Repository navigation
Conversation
Found auditing a public site built with Framework 1.13.4, with axe-core against wcag2a, wcag2aa, wcag21a and wcag21aa. None of the three is reachable from observablehq.config.js: `head` is inserted after the elements, and nothing in the config removes a meta the renderer writes. 1.4.4 Resize text: `maximum-scale=1` stops a reader pinching to zoom, on exactly the devices where magnifying matters most. iOS has ignored it for tap-zoom since iOS 10, so what is left of it is the failure. 1.3.1 Info and relationships: the sidebar's close button was a <label> directly inside the <ol>, where only <li>, <script> and <template> are allowed. Moving it out of the list is the obvious fix and is wrong - the button is `position: absolute` and the first list is `position: sticky`, so out of the list its containing block becomes the scrolling <nav> and it scrolls away with the content. It is wrapped in an <li> with `display: contents` instead: no box is generated, the list stays the containing block, and nothing moves. `role="presentation"` keeps the list at one item for assistive technology. 4.1.2 Name, role, value: the search field had a placeholder and no accessible name. A placeholder is not one - it disappears on the first keystroke, and several screen readers never announce it. The placeholder stays. 63 snapshots change with them: 61 for the viewport, 42 for the sidebar, 3 for the search field.
oluies
marked this pull request as ready for review
October 26, 2026 23:12
axe-core's list rule still fails an <li role="presentation"> as a child of <ol>
("List element has direct children that are not allowed: [role=presentation]"), so the
1.3.1 failure this branch fixes was not fixed. aria-hidden takes the wrapper out of the
accessibility tree, which axe skips, and the list stays one item for assistive technology.
The close label is empty and mouse-only; keyboard and screen-reader users have the
#observablehq-sidebar-toggle checkbox.
Author
|
Could a maintainer approve the workflow run for In the meantime, Thanks! |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three of the four defects in #2059 . The fourth, the missing
langon<html>, is a config question that overlaps #865 and #2054, so it is not here.1.4.4 Resize text — drop
maximum-scale=1One line in
src/render.ts. The directive stops a reader pinching to zoom; iOS has ignored itfor tap-zoom purposes since iOS 10, so what remains of it is the failure.
1.3.1 Info and relationships — the sidebar's close button is wrapped in an
<li>Only
<li>,<script>and<template>may be children of<ol>, and the close<label>was adirect child.
Moving it out of the list is the obvious fix and is wrong:
#observablehq-sidebar-closeisposition: absolute, the list is its containing block, and the first list isposition: sticky.Out of the list, the button's containing block becomes the scrolling
<nav>and it scrolls awaywith the content. So it is wrapped in
<li class="observablehq-sidebar-close-item" aria-hidden="true">withdisplay: contents, which generates no box — the containing blockstays the list and nothing moves.
aria-hiddenrather thanrole="presentation": axe-core'slistrule still fails an<li role="presentation">as a child of<ol>("List element has direct children that are notallowed: [role=presentation]"), so that version did not fix the failure.
aria-hiddentakes thewrapper out of the accessibility tree, which axe skips, and the list stays at one item for
assistive technology. Nothing is lost by hiding it: the close label is empty and mouse-only, and
keyboard and screen-reader users have the
#observablehq-sidebar-togglecheckbox. The label is notfocusable, so
aria-hidden-focusdoes not apply.4.1.2 Name, role, value —
aria-labelon the search fieldThe placeholder stays; a placeholder is not an accessible name, since it disappears on the first
keystroke and several screen readers never announce it.
Snapshots
61 test snapshots change: 61 for the viewport line, 42 for the sidebar list, 3 for the search
input. They are mechanical substitutions of exactly those three strings.
Tests
yarn test:mochain anode:20container, each from a clean checkout with a freshyarn install, on this branch and on85e843efor comparison:85e843e6dd84a9(this branch)The same two failures on both, and neither is mine:
test/input/build/archives.posixwants azipthe container does not have, andpath-test.js:160fails there too before any change.test:lint,test:prettierandtest:tscall pass on this branch.How it was found
An audit of a public site built with Framework 1.13.4, with axe-core 4.10.2 against
wcag2a,wcag2aa,wcag21aandwcag21aa. The site is documentation generated from the EuropeanBanking Authority's data point model, for people who have to fill the templates in.