Skip to content

Brand font @font-face paths resolve incorrectly in Reveal.js theme #14284

@mcanouil

Description

@mcanouil

Bug description

When using _brand.yml with local font files (source: file) in a Reveal.js format, the @font-face declarations generated by the brand system use paths relative to the project root (e.g., fonts/FiraCode-Regular.ttf).
These paths are correct for the HTML format (where the CSS resolves from the document root), but incorrect for Reveal.js.

In Reveal.js, the brand-generated CSS is placed inside the theme at {output}_files/libs/revealjs/dist/theme/, so Pandoc resolves the font URLs relative to that directory, producing invalid paths like:

{output}_files/libs/revealjs/dist/theme/fonts/FiraCode-Regular.ttf

This causes [WARNING] Could not fetch resource for every font file and results in fonts not being embedded when embed-resources: true is set.

Reproducible example

https://github.com/mcanouil/quarto-issues-experiments/tree/main/quarto-cli-14284

_brand.yml:

color:
  primary: "#00C072"

typography:
  fonts:
    - family: Fira Code
      source: file
      files:
        - path: fonts/FiraCode-Regular.ttf
          weight: 400
          style: normal
  base:
    family: Fira Code

example.qmd:

---
title: Brand fonts in Reveal.js
format:
  revealjs:
    embed-resources: true
---
quarto render example.qmd

Expected behaviour

Font files should be resolved relative to the project root (same as in the HTML format) and embedded correctly when embed-resources: true.

Actual behaviour

[WARNING] Could not fetch resource example_files/libs/revealjs/dist/theme/fonts/FiraCode-Regular.ttf
Output created: example.html

The @font-face declarations exist in the output CSS but point to non-existent paths.
Fonts are not embedded and fall back to browser defaults.

Comparison with HTML format

The same _brand.yml works correctly for the html format.
The HTML format resolves @font-face URLs from the document root, where fonts/... is a valid path.

Workaround

Inject @font-face declarations via include-in-header with a <style> block.
Resources referenced from <style> blocks in the HTML <head> are resolved relative to the document root, so the paths work correctly.

format:
  revealjs:
    embed-resources: true
    include-in-header:
      - fonts.html

Where fonts.html contains:

<style>
  @font-face {
    font-family: "Fira Code";
    src: url("fonts/FiraCode-Regular.ttf");
    font-weight: 400;
    font-style: normal;
  }
</style>

The brand-generated @font-face warnings still appear, but the include-in-header fonts are resolved and embedded correctly.

Environment

Quarto 1.9.36
[✓] Checking environment information...
      Quarto cache location: /home/mcanouil/.cache/quarto
[✓] Checking versions of quarto binary dependencies...
      Pandoc version 3.8.3: OK
      Dart Sass version 1.87.0: OK
      Deno version 2.4.5: OK
      Typst version 0.14.2: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
      Version: 1.9.36
      Path: /opt/quarto/bin
[✓] Checking tools....................OK
      TinyTeX: (not installed)
      Chromium: (not installed)
[✓] Checking LaTeX....................OK
      Tex:  (not detected)
[✓] Checking basic markdown render....OK
[✓] Checking R installation...........OK
      Version: 4.5.2
      Path: /opt/R/4.5.2/lib/R
      knitr: 1.51
      rmarkdown: 2.30
[✓] Checking Knitr engine render......OK
[✓] Checking Python 3 installation....OK
      Version: 3.12.3
      Path: /usr/bin/python3
      Jupyter: (None)
  • OS: Linux (WSL2)

Metadata

Metadata

Assignees

No one assigned

    Labels

    brand`_brand.yml`bugSomething isn't workingrevealjsIssues with the revealjs format

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions