Skip to content

Page navigation links do not expose their direction to assistive technology #14804

Description

@cwickham

I have:

  • searched the issue tracker for similar issues
  • installed the latest version of Quarto CLI
  • formatted my issue following the Bug Reports guide

Bug description

Websites with page-navigation: true render prev/next links at the bottom of each page. Books render them by default. Each link has an aria-label that holds the target page title only. The arrow icon shows the direction, but only visually. The accessible name of the link is the bare title, "Home", so a screen reader user cannot tell if the link goes back or forward.

The direction is information that the page presents visually but not programmatically. This fails WCAG 2.2 1.3.1 Info and Relationships (Level A).

The links come from this template:

<nav class="page-navigation">
<div class="nav-page nav-page-previous">
<% if (nav.prevPage) { %>
<a href="<%- nav.prevPage.href %>" class="pagination-link" aria-label="<%- nav.prevPage.plainText || nav.prevPage.text %>">
<i class="bi bi-arrow-left-short"></i> <span class="nav-page-text"><%= nav.prevPage.text %></span>
</a>
<% } %>
</div>
<div class="nav-page nav-page-next">
<% if (nav.nextPage) { %>
<a href="<%- nav.nextPage.href %>" class="pagination-link" aria-label="<%- nav.nextPage.plainText || nav.nextPage.text %>">
<span class="nav-page-text"><%= nav.nextPage.text %></span> <i class="bi bi-arrow-right-short"></i>
</a>
<% } %>
</div>
</nav>

A fix can prefix the direction in the label: aria-label="Previous: Home", via two new localizable strings in _language.yml. The visible link text stays inside the label, so 2.5.3 Label in Name still passes.

Two nearby points, to head off confusion:

This affects quarto.org

For example, docs/interactive/ojs shows both links, labelled "Overview" and "Libraries". Neither label says which one goes back.

Steps to reproduce

Create a website project with three files:

_quarto.yml

project:
  type: website
website:
  title: "Reprex"
  page-navigation: true
  sidebar:
    contents:
      - index.qmd
      - about.qmd

index.qmd

---
title: Home
---

Some content.

about.qmd

---
title: About
---

More content.

Render the project. Then read the markup of nav.page-navigation in _site/about.html.

Actual behavior

<nav class="page-navigation">
  <div class="nav-page nav-page-previous">
      <a href="./index.html" class="pagination-link" aria-label="Home">
        <i class="bi bi-arrow-left-short"></i> <span class="nav-page-text">Home</span>
      </a>
  </div>
  <div class="nav-page nav-page-next">
  </div>
</nav>

The accessible name of the link is "Home". Nothing in the accessibility tree says the link goes to the previous page.

Expected behavior

The accessible name includes the direction, for example "Previous: Home".

Your environment

  • Positron 1.124.0
  • macOS 26.5.2 (build 25F84)

Quarto check output

Quarto 1.10.18
[✓] Checking environment information...
      Quarto cache location: /Users/charlottewickham/Library/Caches/quarto
[✓] Checking versions of quarto binary dependencies...
      Pandoc version 3.10.0: OK
      Dart Sass version 1.101.0: OK
      Deno version 2.7.14: OK
      Typst version 0.15.1: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
      Version: 1.10.18
      Path: /Applications/quarto/bin
[✓] Checking tools....................OK
      TinyTeX: v2026.04
      Chrome Headless Shell: 150.0.7871.115
      VeraPDF: 1.28.2
[✓] Checking LaTeX....................OK
      Using: TinyTex
      Path: /Users/charlottewickham/Library/TinyTeX/bin/universal-darwin
      Version: 2026
[✓] Checking Chrome Headless....................OK
      Using: Chrome Headless Shell installed by Quarto
      Path: /Users/charlottewickham/Library/Application Support/quarto/chrome-headless-shell/chrome-headless-shell-mac-arm64/chrome-headless-shell
      Version: 150.0.7871.115
[✓] Checking basic markdown render....OK
[✓] Checking R installation...........OK
      Version: 4.6.0
      Path: /Library/Frameworks/R.framework/Versions/4.6/Resources
      LibPaths:
        - /Users/charlottewickham/Library/R/arm64/4.6/library
        - /Library/Frameworks/R.framework/Versions/4.6/Resources/library
      knitr: 1.51
      rmarkdown: 2.31
[✓] Checking Knitr engine render......OK
[✓] Checking Python 3 installation....OK
      Version: 3.12.2
      Path: /Users/charlottewickham/.pyenv/versions/3.12.2/bin/python3
      Jupyter: 5.9.1
      Kernels: python3
[✓] Checking Jupyter engine render....OK
[✓] Checking Julia installation...

AI helped investigate this issue, grounded in a local clone of quarto-cli (see CONTRIBUTING.md, "Using AI tools to investigate").

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions