a11y: logos without alt text are handled inconsistently across formats
@cderv is already working on this.
Since Jul 8, 2026.
Assessment
This issue has not been assessed yet.
Description
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
Logo alt text is settable across formats — websites via logo-alt, typst and revealjs via logo: {path, alt}.
This issue is about the default when no alt is provided: the format pipelines disagree, and two of them produce inaccessible output rather than a safe fallback.
When a logo (navbar/sidebar logo, revealjs slide logo, or typst logo) is rendered without alt text, they emit:
| Path | Emitted markup for a logo with no alt | Source |
|---|---|---|
| HTML website navbar | <img … alt="" …> |
navbrand.ejs#L6-L9 |
| HTML website sidebar | <img … alt="" …> |
sidebar.ejs#L40-L43 |
| revealjs slide logo | <img …> — alt attribute omitted |
format-reveal.ts#L409-L416 |
| Typst title-page logo | image(...) — alt parameter omitted |
page.typ#L14 |
HTML defaults a missing logo alt to an empty alt=""; revealjs and Typst leave the attribute off entirely.
This matters because empty vs. absent alt are not equivalent for accessibility:
<img alt="">is a valid decorative-image signal — assistive tech skips it, and axe-core'simage-altrule passes.<img>with noaltattribute fails axe-coreimage-alt(taggedwcag2a/wcag111→ WCAG 2.2 SC 1.1.1 Non-text Content, Level A), and screen readers commonly announce the image filename instead.
So on the same input (a logo with no alt), a Quarto website is conformant while a reveal deck produces a Level A failure — and the Typst PDF's logo has no text alternative.
Investigation was AI-assisted, grounded in a local clone of this repo (source pinned to
50f3d27) and reproduced with Quarto 1.10.12, per CONTRIBUTING.md's note on using AI tools.
The design question
Fixing the inconsistency forces a decision about the intended default, which is really the point of this issue.
Our options are:
- Assume logos are decorative → emit
alt=""everywhere. Make revealjs/Typst match HTML. Simplest; no broken output; passes axe. Downside: it silently passes — an author who forgot alt on a genuinely meaningful logo is never told, becausealt=""conforms. - Emit
alt=""everywhere and warn at render time when a logo resolves with no alt, plus an explicit opt-out to mark a logo decorative and suppress the warning. Alerts every author at build time while keeping output safe. Downside: more work; needs a "decorative" flag and could be noisy for logos that legitimately sit next to visible title text. - Something else?
I think omit alt as a default isn't an option. This leads to an outright 1.1.1 failure that will only get picked up if an author runs a check.
So at minimum revealjs and typst should stop omitting the attribute. The open question is whether the default should stay a silent alt="" (option 1) or gain a warning (option 2).
For context, logos are often decorative but not always. For example, a navbar logo that includes the site/organization name (that isn't otherwise in the navbar).
Steps to reproduce
---
title: "Logo alt test"
format: revealjs
logo: logo.svg
---
## Slide one
Content.
Render, then inspect the emitted logo:
quarto render deck.qmd
grep -oE '<img[^>]*slide-logo[^>]*>' deck.html
Actual behavior
Same input, no alt specified — divergent output:
revealjs: <img src="logo.svg" class="slide-logo"> # no alt
website: <img src="./logo.svg" alt="" class="navbar-logo light-content"> # alt=""
The revealjs <img> has no alt attribute → axe-core image-alt violation (WCAG 1.1.1, Level A); screen readers may read logo.svg. The Typst pipeline likewise omits the alt: parameter on the title-page logo.
Expected behavior
Consistent handling across formats.
Your environment
- IDE: Positron (CLI render; IDE-independent)
- OS: macOS 26.5.1 (25F80)
Quarto check output
Quarto 1.10.12
[✓] Checking environment information...
Quarto cache location: /Users/charlottewickham/Library/Caches/quarto
[✓] Checking versions of quarto binary dependencies...
Pandoc version 3.8.3: OK
Dart Sass version 1.87.0: OK
Deno version 2.7.14: OK
Typst version 0.14.2: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
Version: 1.10.12
Path: /Applications/quarto/bin
[✓] Checking tools....................OK
TinyTeX: v2026.04
VeraPDF: 1.28.2
Chrome Headless Shell: (not installed)
[✓] Checking LaTeX....................OK
Using: TinyTex
Path: /Users/charlottewickham/Library/TinyTeX/bin/universal-darwin
Version: 2026
[✓] Checking Chrome Headless....................OK
Using: Chrome found on system
Path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
Source: MacOS known location
[✓] 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...
- Dominant language
- JavaScript
- Stars
- 6k
- Forks
- 458
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 41
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from quarto-dev/quarto-cli
-
binder bug
Difficulty 1/5 Under an hour Newbie friendliness 92/100
quarto-dev/quarto-cli#14907 · 3 comments ·
-
brand bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
quarto-dev/quarto-cli#14891 ·
-
brand bug html revealjs
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
quarto-dev/quarto-cli#14882 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
quarto-dev/quarto-cli#14875 ·
-
Percent scripts: accept raw-string (r""") and '''-delimited markdown cells, as jupytext writes them Openengines-jupyter enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
quarto-dev/quarto-cli#14850 · 2 comments ·
All issues in quarto-dev/quarto-cli
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
avniproject/avni-client#2135 ·
-
automated broken-link
Difficulty 1/5 Under an hour Newbie friendliness 85/100
-
agent/security hive/hosted-available-lke648397-260827-5n31 security
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
babalae/bettergi-scripts-list#3674 ·
-
A-Release-Notes C-Editing D-Modest S-Ready-For-Implementation
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
bevyengine/bevy-website#2595 ·