fix: WCAG AA accessibility pass — landmarks, nav, alt text, headings, accordion#625
fix: WCAG AA accessibility pass — landmarks, nav, alt text, headings, accordion#625thostetler wants to merge 23 commits intomasterfrom
Conversation
- Add alt text to thumbnail images in news, general, and technical-posts listing pages - Fix contrast and layout issues in blog layout and post templates - Fix shared navbar dropdown role attribute and footer link target sizes - Add alt text to results chart image in nasa-open-access post - Add docker-based local dev config
… sia-r53, sia-r77, sia-r68)
… sia-r77, sia-r68, sia-r2)
- Fix fallback logo alt text to "ADS/SciX logo" on all listing pages - Convert darkSwitch div to button with aria-label; sync aria-label on toggle - Replace line-height: 44px with padding-block on list links - Update .press-coverage-header CSS selector from h4 to h3 - Remove redundant role="banner" from semantic <header> - Update newsletter signup links from http to https
…r13, sia-r64) - sia-r4: add lang="en" to all layout html elements and static api docs - sia-r13: add descriptive title attributes to all YouTube iframes - sia-r64: guard h2.post-title with if page.title to prevent empty headings
…-r13, sia-r64) - Trim whitespace from dynamically derived iframe title in scixhelp - Add if page.title guard to blog_page_scix.html h1.post-title
- Invert <a><li> to <li><a> in all list-group sections of both left-nav include files (left-nav.html and left-nav_scix.html) - Update _sidebar.scss: zero out li.list-group-item padding and move it to the child anchor, making the anchor block-level and full-row clickable with a 44px minimum tap target - Preserve active state styling and hover background on the anchor
- Add > a { color } nested rule inside li.active.list-group-item in
_sidebar.scss so the anchor inherits the active blue (#2169DA)
reliably, not just from cascade on the li
- Same fix in _darkmode.scss for dark mode active link color
- Replace :hover/:focus grouping with separate :hover and :focus-visible
rules on li.list-group-item > a; add explicit outline (2px solid
#4073dd, offset -2px) on :focus-visible for keyboard nav visibility
(outline: none is not globally set for anchors; only .btn-link:focus
and Bootstrap component-scoped rules suppress it)
Add <main> to layouts that were serving page content outside any landmark region. Fixes 6 root layouts across ADS and SciX sections. - default_layout.html: .page-content div → <main> - help_layout.html: .page-content div → <main> - blog_layout.html: .page-content div → <main> - home.html: .home-page-content div → <main> - ads_to_scix.html: bare content div → <main> - ads_to_scix_quick_start.html: .page-content div → <main> Layouts skipped (already have <main>): - help_layout_scix.html (existing <main> on line 14) - blog_layout_scix.html (existing <main> on line 28) Layouts skipped (nesting risk — child layout emits <main>): - about_layout.html (about.html child emits <main>) - about_layout_scix.html (about_scix.html child emits <main>)
Replace <a role="button"> collapse triggers with native <button> elements across both left-nav includes (ADS and SciX variants). Switches Bootstrap 3 collapse binding from href to data-target. Also fixes two pre-existing aria-labelledby mismatches in left-nav.html (troubleshooting and videos sections pointed to wrong or nonexistent ids). Updates _sidebar.scss to target button instead of a within .panel-heading.
Remove invalid tablist/tab/tabpanel roles from left-nav.html — those roles require strict ownership rules not met by this markup structure. Remove aria-multiselectable from left-nav_scix.html panel-group div which had no role to host it. Replace flow-content <div> inside each <button> with <span> (valid phrasing content per HTML spec) across both nav includes. Add aria-hidden="true" to all decorative Font Awesome caret icons. Extend dark mode .left-nav color rule in _darkmode.scss to cover button elements alongside the existing anchor rule.
- Blog listing templates (blog/index.md and subcategory pages): add
alt="{{ post.title }}" for post thumbnails and alt="ADS logo" for
the fallback logo image; fixes ~50 missing alts on /blog and
subcategory listing pages
- help/actions/visualize.md: add descriptive alt to scatter-plot,
word-cloud, and svg-crowbar screenshots
- help/userpreferences/myads.md: add descriptive alt to 6 myADS
setup screenshots (setup_blank x2, arxiv, citations, keywords,
general, begin_import)
- help/gettingstarted/build-library.md: add descriptive alt to 6
library screenshots (export, citation-helper, metrics, author_network
and their SciX gif counterparts)
- help/gettingstarted/searching-for-paper.md: add descriptive alt to
filter-facet screenshot and its SciX counterpart
- help/api/api-docs*.html: add alt="ADS logo" to the nav logo image
in all three API docs pages
- faqs.md: h5 questions promoted to h3 under h2 section headings (21 headings) - data-faq.md: h5 questions promoted to h3 under h2 section headings (15 headings) - export.md: h6 format category headings promoted to h4 under h3 parent (3 headings) - terms-of-use.md: h3 Acknowledgements promoted to h2 under h1 page title (1 heading) - help/orcid, libraries, userpreferences: h1 page titles demoted to h2 so h3 post titles no longer skip - scixhelp/orcid-scix, libraries-scix, userpreferences-scix: same h1 to h2 correction - help/api, scixhelp/api-scix: h3 page title promoted to h2, h4 sub-section to h3
There was a problem hiding this comment.
Pull request overview
WCAG 2.1 AA accessibility pass across the site (landmarks, headings, nav/accordion semantics, media accessible names, tap target sizes), plus a Docker-based dev workflow.
Changes:
- Reworked navigation/accordion markup to be keyboard-accessible and fixed invalid list markup.
- Added accessible names (alt text, iframe titles) and improved heading/landmark structure across layouts and content.
- Introduced Docker Compose + helper script for local development/builds.
Reviewed changes
Copilot reviewed 111 out of 111 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| scixhelp/userpreferences-scix/index.html | Adjust heading level for help landing page content |
| scixhelp/orcid-scix/index.html | Adjust heading level for help landing page content |
| scixhelp/libraries-scix/index.html | Adjust heading level for help landing page content |
| scixhelp/index.md | Add accessible iframe title for dynamically created video embeds |
| scixhelp/api-scix/index.html | Adjust heading levels on API help page |
| scixblog/technical-posts/index.md | Add page title + thumbnail alt text |
| scixblog/news/index.md | Add page title + thumbnail alt text |
| scixblog/index.md | Add page title, switch signup link to HTTPS, add thumbnail alt text |
| scixblog/general/index.md | Add page title + thumbnail alt text |
| run | Add Docker Compose wrapper script for common dev/build tasks |
| help/userpreferences/index.html | Adjust heading level for help landing page content |
| help/orcid/index.html | Adjust heading level for help landing page content |
| help/libraries/index.html | Adjust heading level for help landing page content |
| help/common/js/dark-mode-switch.js | Improve dark mode toggle accessibility labeling |
| help/api/index.html | Adjust heading levels on API help page |
| help/api/api-docs.html | Add lang + logo alt text |
| help/api/api-docs-internal.html | Add lang + logo alt text |
| help/api/api-docs-all.html | Add lang + logo alt text |
| docker-compose.yml | Add Docker Compose services/profiles for Jekyll workflows |
| blog/technical-posts/index.md | Add thumbnail alt text |
| blog/news/index.md | Add thumbnail alt text |
| blog/index.md | Add thumbnail alt text |
| blog/general/index.md | Add thumbnail alt text |
| _sass/_sidebar.scss | Style accordion triggers as buttons; improve focus styles; enlarge tap targets |
| _sass/_layout.scss | Improve tap target sizing, line-height, footer link targets, and label contrast |
| _sass/_darkmode.scss | Improve dark mode toggle contrast/size; ensure nav items remain readable |
| _layouts/post_scix.html | Avoid emitting empty post title heading |
| _layouts/post.html | Avoid emitting empty post title heading |
| _layouts/home.html | Add lang; wrap content in <main> for landmark coverage |
| _layouts/help_layout.html | Add lang; wrap content in <main> for landmark coverage |
| _layouts/default_layout.html | Add lang; wrap content in <main> for landmark coverage |
| _layouts/blog_post_scix.html | Reduce heading misuse by rendering author/date as paragraphs |
| _layouts/blog_page_scix.html | Promote page title to <h1> when present |
| _layouts/blog_page.html | Avoid emitting empty page title heading |
| _layouts/blog_layout_scix.html | Add lang, add nav landmark label, convert dark switch to <button>, add <main> |
| _layouts/blog_layout.html | Add lang; wrap content in <main> for landmark coverage |
| _layouts/ads_to_scix_quick_start.html | Add lang; wrap content in <main> for landmark coverage |
| _layouts/ads_to_scix.html | Add lang; wrap content in <main> for landmark coverage |
| _layouts/about_scix.html | Avoid nested nav landmarks; avoid emitting empty post title heading |
| _layouts/about.html | Avoid nested nav landmarks; avoid emitting empty post title heading |
| _includes/left-nav_scix.html | Convert accordion triggers to <button>; fix invalid list markup; add aria-labels |
| _includes/left-nav.html | Convert accordion triggers to <button>; fix invalid list markup; add aria-labels |
| _includes/header_default_scix.html | Remove redundant role="menu" attribute |
| _includes/about-left-nav_scix.html | Add aria-label to about nav landmark |
| _includes/about-left-nav.html | Add aria-label to about nav landmark |
| _includes/_help/videos/_posts/welcome.md | Add iframe title |
| _includes/_help/videos/_posts/personalization.md | Add iframe title |
| _includes/_help/videos/_posts/libraries.md | Add iframe title |
| _includes/_help/videos/_posts/intro.md | Add iframe title |
| _includes/_help/videos/_posts/infrastructure.md | Add iframe title |
| _includes/_help/videos/_posts/fulltext.md | Add iframe title |
| _includes/_help/videos/_posts/experts.md | Add iframe title |
| _includes/_help/videos/_posts/api.md | Add iframe title |
| _includes/_help/videos/_posts/affiliations.md | Add iframe title |
| _includes/_help/videos/_posts/advanced-search.md | Add iframe title |
| _includes/_help/userpreferences/_posts/myads.md | Add iframe title + image alt text |
| _includes/_help/terms/_posts/terms-of-use.md | Adjust heading level to avoid heading skips |
| _includes/_help/index.md | Add iframe title |
| _includes/_help/gettingstarted/_posts/searching-for-paper.md | Add image alt text |
| _includes/_help/gettingstarted/_posts/build-library.md | Add image alt text |
| _includes/_help/faq/_posts/faqs.md | Normalize question headings to reduce heading skips |
| _includes/_help/data_faq/_posts/data-faq.md | Normalize question headings to reduce heading skips |
| _includes/_help/actions/_posts/visualize.md | Add image alt text |
| _includes/_help/actions/_posts/export.md | Normalize heading levels |
| _includes/_blogcontent/2025-09-29-scix-launch.md | Add alt text; adjust press coverage heading level |
| _includes/_blogcontent/2025-08-25-scix-data-collections.md | Add alt text; normalize section headings |
| _includes/_blogcontent/2025-07-01-scix-visualizations.md | Add alt text; normalize section headings |
| _includes/_blogcontent/2025-03-25-what-i-wish-i-knew-about-ads-scix-during-my-phd.md | Add alt text |
| _includes/_blogcontent/2025-02-27-scix-earth-science-literature-review.md | Add alt text |
| _includes/_blogcontent/2025-02-27-scix-ambassador-workshop.md | Add alt text |
| _includes/_blogcontent/2024-08-01-data-linking-III.md | Add alt text |
| _includes/_blogcontent/2024-07-01-data-linking-II.md | Add alt text |
| _includes/_blogcontent/2024-06-13-data-linking-I.md | Add alt text |
| _includes/_blogcontent/2024-06-04-HistoricLit.md | Add alt text |
| _includes/_blogcontent/2024-03-06-introducing-scix-ambassador-program.md | Normalize headings; add alt text |
| _includes/_blogcontent/2024-02-26-userfeedback-2024.md | Normalize headings; add alt text |
| _includes/_blogcontent/2024-01-03-aas-2024.md | Add alt text |
| _includes/_blogcontent/2023-10-23-ads-models-and-datasets.md | Normalize headings; add alt text |
| _includes/_blogcontent/2023-04-19-scix.md | Add alt text |
| _includes/_blogcontent/2023-03-20-curation-model.md | Add alt text |
| _includes/_blogcontent/2022-12-29-uat-integration.md | Replace footnote structure for clarity |
| _includes/_blogcontent/2022-09-06-ads-object-search.md | Inline prior footnote content; add alt text |
| _includes/_blogcontent/2021-11-12-arc-ssad-project.md | Normalize headings |
| _includes/_blogcontent/2021-08-04-openapi-docs.md | Add alt text |
| _includes/_blogcontent/2021-04-15-affils-update.md | Normalize headings; add alt text |
| _includes/_blogcontent/2020-08-10-the_new_myADS.md | Add alt text |
| _includes/_blogcontent/2020-05-29-ui-updates.md | Add alt text |
| _includes/_blogcontent/2020-04-06-nasa-open-access.md | Add alt text |
| _includes/_blogcontent/2020-01-15-affiliations-feature.md | Normalize headings; add alt text |
| _includes/_blogcontent/2019-05-30-ave-atque-vale.md | Add alt text |
| _includes/_blogcontent/2019-04-11-transition-reminder.md | Normalize headings; add alt text |
| _includes/_blogcontent/2019-03-26-citations-journals-3.md | Add alt text |
| _includes/_blogcontent/2019-02-13-updates2.md | Switch newsletter link to HTTPS; normalize headings; add alt text |
| _includes/_blogcontent/2018-10-22-citations-journals-2.md | Normalize headings; add alt text |
| _includes/_blogcontent/2018-08-20-citations-journals.md | Add alt text |
| _includes/_blogcontent/2018-07-17-concepts-at-work.md | Add alt text |
| _includes/_blogcontent/2018-05-24-transition.md | Normalize headings |
| _includes/_blogcontent/2018-04-11-updates.md | Normalize headings |
| _includes/_blogcontent/2018-02-05-asclepias.md | Replace markdown tables with semantic HTML tables; add alt text |
| _includes/_blogcontent/2017-12-12-adsug.md | Normalize headings |
| _includes/_blogcontent/2017-10-05-100M-citations.md | Add alt text to images |
| _includes/_blogcontent/2016-03-16-open-access-and-nasa-data.md | Add alt text |
| _includes/_blogcontent/2016-02-17-building-an-app.md | Normalize headings; add alt text |
| _includes/_blogcontent/2015-11-17-discovering-long-fuse-papers.md | Add alt text |
| _includes/_blogcontent/2015-11-03-ads-private-libraries.md | Add alt text |
| _includes/_blogcontent/2015-10-21-visualising-metrics-with-bbb.md | Add alt text |
| _includes/_blogcontent/2015-07-15-introducing-bumblebee.md | Add alt text |
| _config.yml | Exclude Docker/dev artifacts from the Jekyll build |
| README.md | Document Docker-based dev workflow |
| Dockerfile | Add container image for consistent Jekyll builds |
| .dockerignore | Reduce Docker build context and avoid copying build artifacts |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| serve: | ||
| extends: jekyll | ||
| ports: | ||
| - "127.0.0.1:${JEKYLL_PORT:-4000}:4000" | ||
| - "127.0.0.1:35729:35729" | ||
| command: bundle exec jekyll serve --host 0.0.0.0 --livereload | ||
| profiles: [serve] | ||
|
|
||
| dev: | ||
| extends: jekyll | ||
| command: bundle exec jekyll build --watch --incremental --force_polling | ||
| profiles: [dev] | ||
|
|
||
| build: | ||
| extends: jekyll | ||
| command: bundle exec jekyll build | ||
| profiles: [build] |
There was a problem hiding this comment.
extends: jekyll is not valid Compose syntax. extends must be a mapping (e.g., extends: { service: jekyll }), or you can replace this with YAML anchors/aliases (or x- extension fields) to share the base service config. As-is, docker compose will fail to parse the file.
|
|
||
| usage() { | ||
| cat <<EOF | ||
| Usage: ./site <command> |
There was a problem hiding this comment.
The usage text references ./site, but the provided script is named run and the README examples use ./run .... Update the usage string to match the actual entrypoint so users don’t get misdirected.
| Usage: ./site <command> | |
| Usage: ./run <command> |
| const iframe = document.createElement('iframe'); | ||
| // Add enablejsapi=1 to enable YouTube API control | ||
| iframe.src = 'https://www.youtube.com/embed/' + videoYoutubeId + '?autoplay=1&enablejsapi=1'; | ||
| iframe.setAttribute('title', videoTitle); |
There was a problem hiding this comment.
iframe.title is set from an <h3> lookup that can resolve to an empty string; an empty title typically still fails 'iframe has an accessible name' checks. Provide a non-empty fallback (e.g., a generic 'Video' label or use another attribute like data-title) before setting the attribute.
| const iframe = document.createElement('iframe'); | |
| // Add enablejsapi=1 to enable YouTube API control | |
| iframe.src = 'https://www.youtube.com/embed/' + videoYoutubeId + '?autoplay=1&enablejsapi=1'; | |
| iframe.setAttribute('title', videoTitle); | |
| const effectiveTitle = videoTitle || 'Video'; | |
| const iframe = document.createElement('iframe'); | |
| // Add enablejsapi=1 to enable YouTube API control | |
| iframe.src = 'https://www.youtube.com/embed/' + videoYoutubeId + '?autoplay=1&enablejsapi=1'; | |
| iframe.setAttribute('title', effectiveTitle); |
_layouts/default_layout.html
Outdated
| {% include footer_default.html %} | ||
| <div id="darkSwitch" class="darkmode-toggle" title="Turn on dark mode"> |
There was a problem hiding this comment.
The dark mode control is still a <div> in this layout, which is not keyboard-operable by default (and won’t behave like a button for assistive tech). Since _layouts/blog_layout_scix.html already converts this to a real <button type=\"button\"> with aria-label, consider updating the remaining layouts to use <button> as well for consistent keyboard accessibility.
help/userpreferences/index.html
Outdated
| --- | ||
|
|
||
| <h1> User Preferences </h1> | ||
| <h2> User Preferences </h2> |
There was a problem hiding this comment.
This change demotes a top-level page heading from <h1> to <h2>. If the surrounding layout does not provide an <h1>, the page may end up without a top-level heading, which is problematic for screen reader navigation and expected document outline. Consider keeping this as <h1> (or ensure the layout emits exactly one <h1> and content starts at <h2>).
| <h2> User Preferences </h2> | |
| <h1> User Preferences </h1> |
- Convert all dark mode toggle divs to semantic buttons with aria-label across all 10 layouts and 3 API docs pages - Restore h1 page headings in help index pages (userpreferences, orcid, libraries, api) and promote sub-section h3 to h2 for proper hierarchy - Add fallback title for dynamically created video iframes in scixhelp - Add border/padding reset to .darkmode-toggle for button element
Incorporate upstream's post.hidden filter while keeping h1/h2 heading hierarchy from a11y fixes.
1d2d912 to
e72b62b
Compare
Add min-height to .search-bar-container in both _layout.scss and help/common/css/styles.scss so the Google CSE widget has allocated space before it loads, eliminating CLS on page navigation. Remove the slideInDown animation that caused a visible fade-in on every page load.
e72b62b to
cf7c797
Compare
…ation" This reverts commit cf7c797.
WCAG 2.1 AA accessibility pass over non-blog pages. Total findings reduced from 26,212 to 10,843 (-58.6%).
Builds on #622 — should be merged after that one lands.