I have:
Bug description
On a page that uses page-layout: custom, Quarto's own title block (#title-block-header) is rendered outside the page's <main> landmark, so it implicitly becomes a second banner landmark alongside the navbar's #quarto-header.
#title-block-header is a <header>, and a <header> computes as banner unless it is inside <main> or sectioning content (HTML-AAM §3.5.49). With the default layout the title block renders inside main#quarto-document-content, so it is not a banner and the page has one. With page-layout: custom there is no <main> at all, so the title block is never nested.
This is the same problem as #14375, #14377 and #14605 — #title-block-header ending up outside <main> — but a different code path. In #14375 the title-block post-processor moves the header out of #quarto-content when title-block-banner: true or title-block-style: manuscript is set. In #14605 the about post-processor re-emits it as a sibling of <main>. Here nothing moves it: the custom layout never opens a <main> for it to sit in.
before-body-article.ejs opens <main class="content">, while before-body-custom.ejs opens only a div, and formatHasArticleLayout selects between them:
|
<main class="content" id="quarto-document-content"> |
|
<div class="page-layout-<%- pageLayout %>"> |
|
|
|
const pageLayout = formatPageLayout(format); |
|
const bodyEnvelope = formatHasArticleLayout(format) |
|
? { |
|
before: renderTemplate("before-body-article.ejs", pageLayout), |
|
afterPreamble: renderTemplate( |
|
"after-body-article-preamble.ejs", |
|
pageLayout, |
|
), |
|
afterPostamble: renderTemplate( |
|
"after-body-article-postamble.ejs", |
|
pageLayout, |
|
), |
|
} |
|
: { |
|
before: renderTemplate("before-body-custom.ejs", kPageLayoutCustom), |
|
afterPreamble: renderTemplate( |
|
"after-body-custom-preamble.ejs", |
|
kPageLayoutCustom, |
|
), |
|
afterPostamble: renderTemplate( |
|
"after-body-custom-postamble.ejs", |
|
kPageLayoutCustom, |
Authors cannot work around this. page-layout: custom hands the body container to the author, so an author can add their own <main> and does get a main landmark. It does not help: Quarto emits #title-block-header before the author's content, so the title block stays outside whatever the author wraps, and the page still has two banners.
Steps to reproduce
A website with page-layout: custom.
_quarto.yml:
project:
type: website
website:
title: "Custom layout site"
navbar:
left:
- href: index.qmd
text: Home
format:
html:
page-layout: custom
index.qmd:
---
title: Custom layout in a website
---
Body text.
Render the site, open _site/index.html, and count the landmarks in the browser console:
document.querySelectorAll('header').length // 2, both computing as banner
document.querySelectorAll('main').length // 0
Removing page-layout: custom from _quarto.yml gives one banner and one main.
Actual behavior
Two banner landmarks and no main. Measured in Chromium with the same site rendered both ways:
default layout banners: 1 mains: 1
header#quarto-header parent=body insideMain=false
header#title-block-header parent=main#quarto-document-content insideMain=true
page-layout: custom banners: 2 mains: 0
header#quarto-header parent=body insideMain=false
header#title-block-header parent=div#quarto-content insideMain=false
axe reports two best-practice violations, both moderate:
landmark-no-duplicate-banner — "Document should not have more than one banner landmark"
landmark-one-main — "Document should have one main landmark"
Adding an author-supplied <main> around the body content clears landmark-one-main (mains: 1) but not the duplicate banner (banners: 2).
A standalone document with page-layout: custom has one banner rather than two, since there is no navbar, but the body content still sits outside every landmark (region).
Expected behavior
The title block that Quarto emits does not become a second banner landmark.
Your environment
- IDE: Positron 2026.08.0 (build 272)
- OS: 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.5.2
Path: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources
LibPaths:
- /Users/charlottewickham/Library/R/arm64/4.5/library
- /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/library
knitr: 1.51
rmarkdown: 2.30
[✓] 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...
Found while reviewing #14739. Part of #8706. AI-assisted investigation, grounded in a local clone of quarto-cli.
I have:
Bug description
On a page that uses
page-layout: custom, Quarto's own title block (#title-block-header) is rendered outside the page's<main>landmark, so it implicitly becomes a secondbannerlandmark alongside the navbar's#quarto-header.#title-block-headeris a<header>, and a<header>computes asbannerunless it is inside<main>or sectioning content (HTML-AAM §3.5.49). With the default layout the title block renders insidemain#quarto-document-content, so it is not a banner and the page has one. Withpage-layout: customthere is no<main>at all, so the title block is never nested.This is the same problem as #14375, #14377 and #14605 —
#title-block-headerending up outside<main>— but a different code path. In #14375 the title-block post-processor moves the header out of#quarto-contentwhentitle-block-banner: trueortitle-block-style: manuscriptis set. In #14605 the about post-processor re-emits it as a sibling of<main>. Here nothing moves it: the custom layout never opens a<main>for it to sit in.before-body-article.ejsopens<main class="content">, whilebefore-body-custom.ejsopens only adiv, andformatHasArticleLayoutselects between them:quarto-cli/src/resources/formats/html/templates/before-body-article.ejs
Line 20 in 7eebb00
quarto-cli/src/resources/formats/html/templates/before-body-custom.ejs
Line 1 in 7eebb00
quarto-cli/src/format/html/format-html-bootstrap.ts
Lines 139 to 161 in 7eebb00
Authors cannot work around this.
page-layout: customhands the body container to the author, so an author can add their own<main>and does get amainlandmark. It does not help: Quarto emits#title-block-headerbefore the author's content, so the title block stays outside whatever the author wraps, and the page still has two banners.Steps to reproduce
A website with
page-layout: custom._quarto.yml:index.qmd:Render the site, open
_site/index.html, and count the landmarks in the browser console:Removing
page-layout: customfrom_quarto.ymlgives one banner and one main.Actual behavior
Two
bannerlandmarks and nomain. Measured in Chromium with the same site rendered both ways:axe reports two best-practice violations, both moderate:
landmark-no-duplicate-banner— "Document should not have more than one banner landmark"landmark-one-main— "Document should have one main landmark"Adding an author-supplied
<main>around the body content clearslandmark-one-main(mains: 1) but not the duplicate banner (banners: 2).A standalone document with
page-layout: customhas one banner rather than two, since there is no navbar, but the body content still sits outside every landmark (region).Expected behavior
The title block that Quarto emits does not become a second banner landmark.
Your environment
Quarto check output
Found while reviewing #14739. Part of #8706. AI-assisted investigation, grounded in a local clone of quarto-cli.