Skip to main content

Multiformat branding with _brand.yml

Overview

Quarto supports brand.yml—a single YAML file that can be used to customize the appearance of your documents across multiple formats. This is particularly useful for organizations that need a unified look across various formats.

As an example, consider the following _brand.yml file:

_brand.yml
color:
  palette:
    dark-grey: "#222222"
    blue: "#ddeaf1"
  background: blue
  foreground: dark-grey
  primary: black

logo:
  medium: logo.png

typography:
  fonts:
    - family: Jura
      source: google
  base: Jura
  headings: Jura

When this _brand.yml is placed in a project, webpages, presentations, PDF reports, and dashboards will share a common appearance:

Screenshot of a webpage. The text is dark grey on a light blue background, using a rounded sans-serif typeface, a logo appears in the navbar.
Webpage: html
Screenshot of a dashboard. The text is dark grey on a light blue background, using a rounded sans-serif typeface, a logo appears in the navbar.
Dashboard dashboard
Screenshot of a presentation. The text is dark grey on a light blue background, using a rounded sans-serif typeface, a logo appears in bottom left of the slide.
Presentation: revealjs
Screenshot of a PDF document. The text is dark grey on a light blue background, using a rounded sans-serif typeface, a logo appears in top right of the page.
PDF: typst

On this page:

  • Learn how to add a brand file.
  • Learn about the elements of brand.yml and how they are used in Quarto.
  • Learn how to access brand values outside of the brand file.
  • See a more comprehensive example.
  • Learn how to migrate projects created without _brand.yml to easily support _brand.yml features.
WarningLimitation

The brand.yml specification is an active area of work at Posit. Quarto’s support for brand.yml is not yet complete. For now, we’ve highlighted places where Quarto doesn’t yet support the full spec with special Limitation callouts, like this one.

Currently, the formats that support brand.yml are: html, dashboard, revealjs and typst.

Applying Brand

Creating Brand Files

A brand takes effect in two steps: the brand file, and the brand: key that points at it.

Create a _brand.yml in the root directory of your project (alongside _quarto.yml):

_brand.yml
color:
  background: "#eeeeee"

Then declare it in _quarto.yml:

_quarto.yml
brand: _brand.yml
ImportantQuarto 2 does not auto-discover _brand.yml

A _brand.yml with no brand: key pointing at it has no effect — your documents render exactly as if the file were not there, with no warning.

This differs from Quarto 1, which applies a _brand.yml found at a handful of fixed paths whether or not anything refers to it. Quarto 2 requires the declaration so that a file’s presence never silently changes how a project renders.

q2 use brand writes both halves for you — see Adding a brand with q2 use brand below.

You can also set brand options directly in a document, with no separate file:

document.qmd
---
brand:
  color:
    background: "#eeeeee"
---

Brand values are plain YAML

Unlike most document metadata, values under brand: are never treated as markdown. Whether a brand lives in _brand.yml, in _quarto.yml, or in a document header, every value is read as plain YAML, exactly as written — a color like "#b22222", a file name like _brand.yml, or a name containing * or _ needs no escaping and no !str tag.

If you do want a value under brand.meta to be processed as markdown, tag it explicitly with !md:

document.qmd
---
brand:
  meta:
    name: !md "Acme *Corp*"
---

Brand-aware tools (such as the theme compiler) see the plain text of an !md value — in this example, Acme Corp.

Document and Project Brand Configuration

This section covers how to configure brand settings for individual documents and projects. If you’re looking to adopt a brand that’s maintained externally—such as a shared organizational brand—see Sharing brands across projects.

If you set brand in a document header, it will replace the entire brand from _brand.yml.

You can disable brand for a document by setting brand to false:

document.qmd
---
brand: false
---

You can put _brand.yml in a subdirectory of your project, and then use the brand key to specify the path to the brand file. For example, to use the brand file at brand/_brand.yml for a single document, add brand to the header:

document.qmd
---
brand: brand/_brand.yml
---

To use the brand file at brand/_brand.yml for all documents in the project add brand to _quarto.yml:

_quarto.yml
brand: brand/_brand.yml

Paths specified in _brand.yml are relative to the location of the brand file.

Light and Dark Colors

To specify colors for both light and dark modes using a single brand.yml file, specify any color in color or typography with an object containing the light and dark colors:

_brand.yml
color:
  background:
    light: "#ffffff"
    dark: "#333333"
  foreground:
    light: "#333333"
    dark: "#ffffff"
typography:
  headings:
    color:
      light: "#111144"
      dark: "#d0d0ff"

This also works with the brand specified directly in the document metadata:

document.qmd
---
brand:
  color:
    background:
      light: "#ffffff"
      dark: "#333333"
    foreground:
      light: "#333333"
      dark: "#ffffff"
  typography:
    headings:
      color:
        light: "#111144"
        dark: "#d0d0ff"
---
WarningLimitation

Colors in the palette cannot currently be specified with light and dark variants.

Light and Dark Brands

If you prefer to author separate light and dark brands for light and dark mode, or you need to customize non-color properties, you can separate the brands into their own files, and specify light and dark brand files:

document.qmd
---
brand:
  light: light-brand.yml
  dark: dark-brand.yml
---

This is similar to how Themes work.

This also works with brands specified directly in the document:

document.qmd
---
brand:
  light:
    color:
      background: "#ffffff"
      foreground: "#333333"
  dark:
    color:
      background: "#333333"
      foreground: "#ffffff"
---

Light and dark brands can also be specified at the project-level:

_quarto.yml
brand:
  light: light-brand.yml
  dark: dark-brand.yml
WarningLimitation

Brand metadata cannot currently be specified directly in _quarto.yml, only via the file syntax.

Brand Mode

The Typst and revealjs formats do not produce outputs which can toggle between light and dark mode dynamically.

By default, Typst and revealjs formats will render using the light brand. Set brand-mode: dark to render using the dark brand.

Typst:

document.qmd
---
format:
  typst:
    brand-mode: dark
---

Revealjs:

document.qmd
---
format:
  revealjs:
    brand-mode: dark
---

Brand Elements

The elements of brand.yml are specified in the documentation for the brand.yml project. In this section, learn how these elements are used in Quarto.

Color

Color in the brand.yml docs

Use color to define your brand’s color palette and map your palette to the roles colors play, a.k.a semantic colors. A simple example might define the value background to a light blue:

_brand.yml
color:
  background: "#ddeaf1"

Use the palette key to define a set of named colors that can be referenced elsewhere in the _brand.yml. For example, you might define blue and set it as the background:

_brand.yml
color:
  palette:
    blue: "#ddeaf1"
  background: blue

The most commonly used semantic colors include foreground, background and primary:

_brand.yml
color:
  palette:
    dark-grey: "#222222"
    blue: "#ddeaf1"
  background: blue
  foreground: dark-grey
  primary: black

The colors foreground and background are used consistently across formats to set the color of the main text and color of the page it appears on. The color primary sets the link color, navbar color (html and dashboard), and progress bar color (revealjs).

For HTML formats that use Bootstrap (html, dashboard) the remaining semantic colors are mapped directly to their Bootstrap counterparts with the same name.

The full list of semantic colors you can set in color is:

Name Description
foreground The main text color. Typically will be close to black and must have high contrast with the background color.
background The main background color. Tyically will be close to white and must have high contrast with the foreground color.
primary The primary accent color, used for hyperlinks, active states, and primary action buttons.
secondary The secondary accent color, often used for lighter text or disabled states.
tertiary The tertiary accent color, used for hover states, accents, and wells.
success The color used for positive or successful actions and information.
info The color used for neutral or informational actions and information.
warning The color used for warning or cautionary actions and information.
danger The color used for errors, dangerous actions, or negative information.
light A bright color, used as a high-contrast foreground color on dark elements or low-contrast background color on light elements.
dark A dark color, used as a high-contrast foreground color on light elements or high-contrast background color on light elements.

You can access both named and semantic colors from your brand in SCSS and using the brand shortcode. See Using _brand.yml values for more details.

Typography

Typography in the brand.yml docs

The typography element allows you to specify fonts and their style. Use fonts to specify a list of fonts to use for your brand:

_brand.yml
typography:
  fonts:
    - family: Jura
      source: google

The properties you can set for a font under fonts depends on the source. You can see the other properties available in our Reference for Brand.

For source: google and source: bunny, weight selects the weights to download: a single value, a list, or a variable-font range written as N..M:

_brand.yml
typography:
  fonts:
    - family: EB Garamond
      source: google
      weight: 400..700

Google Fonts serves a range as one variable font covering the whole span. Bunny Fonts has no range syntax, so Quarto requests each weight in the range separately (400..700 becomes 400,500,600,700). When weight is omitted, weights 400 and 700 are requested.

For source: file, each file may declare the weights it covers; a variable font file declares its range the same way:

_brand.yml
typography:
  fonts:
    - family: My Sans
      source: file
      files:
        - path: fonts/MySans-VariableFont_wght.woff2
          weight: 300..800
        - path: fonts/MySans-Italic.woff2
          weight: 400
          style: italic

Range ends are numbers from 100 to 900 with the smaller first; keywords are not accepted as range ends. A weight Quarto does not recognize stops the render with error Q-14-8, which names the offending value and its location.

Local font files

A font with source: file ships its own files with the project instead of loading them from Google Fonts or Bunny Fonts:

_brand.yml
typography:
  fonts:
    - family: EB Garamond
      source: file
      files:
        - path: fonts/EBGaramond-Regular.woff2
          weight: 400
        - path: fonts/EBGaramond-Italic.woff2
          weight: 400
          style: italic
  base: EB Garamond

Each files entry is a path (or a map with path, weight, and style). Paths are relative to the brand file’s own directory, so the example above expects a fonts/ directory next to _brand.yml. A path that starts with / is relative to the project root instead.

Quarto publishes the files for you: every local font is copied into a fonts/ directory next to the compiled theme stylesheet (site_libs/quarto/fonts/ in a website, <document>_files/fonts/ for a standalone document), and the generated @font-face rule points there. You do not need to list font files under resources. The format() hint of the rule comes from the file’s extension (.woff2, .woff, .ttf, or .otf).

Because published fonts are named by their file name only, two different files in one project cannot share a name — serif/Regular.woff2 and sans/Regular.woff2 would collide. Quarto stops the render and names both files when that happens; rename one of them. A files entry that points at a file which does not exist produces a warning and the render continues without it. Remote fonts (https://… paths) are left for the browser to fetch.

Per-file keys beyond path, weight, and style — such as format or display — are not part of the settled brand.yml specification. Quarto warns and ignores them.

You can then refer to fonts by family in the remaining typography options:

_brand.yml
typography:
  fonts:
    - family: Jura
      source: google
  base: Jura
  headings: Jura

The options base and headings set the typographic style of the main text and headings respectively. Use links to apply specific styles to links. The option monospace sets the typographic style of code in general, and monospace-inline and monospace-block can be further used to style code that appears inline and in blocks respectively:

_brand.yml
typography:
  fonts:
    - family: Jura
      source: google
    - family: Space Mono
      source: google
  base: Jura
  headings: Jura
  link:
    decoration: underline
  monospace: Space Mono
  monospace-inline:
    color: "#222222"
    background-color: "#ddeaf1" # or use a named color from `color`
  monospace-block:
    background-color: "#eef4f8"

The fields allowed for each element differ, expand the callout below to see what is supported in each field.

The full set of text elements that you can style with typography is:

Attribute Description Supported Fields
base Default text, primarily used in the document body.
  • family
  • size
  • line-height
  • weight
headings All heading levels (h1, h2, etc.).
  • family
  • weight
  • style
  • line-height
  • color
monospace General monospaced text, typically used in code blocks and other programming-related content.
  • family
  • size
  • weight
monospace-inline Inline monospaced text, usually used for code snippets within regular text. Inherits from monospace.
  • family
  • size
  • weight
  • color
  • background-color
monospace-block Block (multi-line) monospaced text, typically used for code blocks. Inherits from monospace.
  • family
  • size
  • weight
  • line-height
  • color
  • background-color
link Hyperlinks.
  • weight
  • color
  • background-color
  • decoration

The supported fields are generally described as follows:

  • family: The font family to be used for a typographic element. This should match a font resource declared in typography.fonts.
  • size: The font size for a typographic element. Should be specified using a CSS length unit (e.g., “14px”, “1em”, “0.9rem”).
  • weight: The font weight (or boldness) of the text. Can be a numeric value between 100 and 900, or one of the keywords thin, extra-light, ultra-light, light, normal, regular, medium, semi-bold, demi-bold, bold, extra-bold, ultra-bold, or black. A text element takes a single weight; ranges belong on the font declaration under fonts (see below). Any other value is an error.
  • style: The font style for the text, typically either “normal” or “italic”.
  • line-height: The line height of the text, which refers to the vertical space between lines. Often expressed as a multiple of the font size or in fixed units.
  • color: The color of the text. Can be any CSS-compatible color definition or a reference to a color defined in the brand’s color palette.
  • background-color: The background color for the text element. Can be any CSS-compatible color definition or a reference to a color defined in the brand’s color palette.
  • decoration: The text decoration, typically used for links. Common values include “underline”, “none”, or “overline”.

Typst

See the Advanced documentation for more details on the Typst implementation, and troubleshooting tips for fonts.

Defaults

Defaults in the brand.yml docs

The defaults section of brand.yml allows users to set options for specific tools that don’t otherwise fit into the brand.yml schema. Quarto’s implementation currently supports defaults: bootstrap.

Bootstrap

The bootstrap section of defaults follows brand.yml and applies to the html and dashboard formats. Quarto merges the options set under defaults: bootstrap in the appropriate layer of Quarto’s SCSS layering system.

The defaults option inside bootstrap, can take a string, or key-value pairs corresponding to SCSS variable name-value pairs. Building on our initial example, you could use bootstrap: defaults to set the SCSS variables link-decoration and navbar-fg:

_brand.yml
defaults:
  bootstrap:
    defaults: # defaults also supports a string as its value
      link-decoration: underline
      navbar-fg: "#fff"

The resulting HTML pages will have links that are underlined and use white for text in the navigation bar.

Screenshot of a webpage. The text is dark grey on a light blue background, using a rounded sans-serif typeface, a logo appears in the navbar.
Without defaults: bootstrap setting
Screenshot of a webpage. It looks identical to the previous image, except for underlined links and white text on the navbar.
With defaults: bootstrap setting: note the link decoration and the white color for the navbar text

In addition to the defaults option, Quarto supports uses, functions, mixins and rules, which all take a string value. For example, you could use rules to provide a CSS rule to remove the border below second-level headings:

_brand.yml
defaults:
  bootstrap:
    # uses: <string>
    # functions: <string>
    # mixins: <string>
    rules: |
      h2 {
        border: none;
      }

Meta

Meta in the brand.yml docs

You can set brand metadata using the meta key:

_brand.yml
meta:
  name: Acme Corporation
  link: https://www.acmecorp.com
WarningLimitation

Quarto does nothing with meta values.

Using _brand.yml values

Beyond the automatic application of your brand file, you can also directly access _brand.yml values in Quarto documents. In this section, you’ll learn how to use the brand shortcode, use brand variables in SCSS files, and some format-specific ways to use access brand values.

Shortcode - {{< brand >}}

Some values from the _brand.yml configuration file can be accessed via the brand shortcode. In particular, you can access colors and logos by name:

  • Use {{< brand color COLOR_NAME VARIANT >}} to return the brand color named COLOR_NAME as a string.
  • Use {{< brand logo LOGO_NAME VARIANT >}} to return the brand logo named LOGO_NAME as an image.

VARIANT is optional:

  • For the brand color shortcode, the default is light. To return the color from the dark brand use dark.
  • For the brand logo shortcode, the default is both, which will expand to both light and dark logos with the appropriate classes for mode-specific content so that the light logo shows in light mode and the dark logo shows in dark mode.
Note

If the VARIANT is light or dark, the brand logo shortcode will not add a mode-specific class.

For example, you could use the shortcode to place a brand image you’ve named icon in a dashboard sidebar:

dashboard.qmd
---
format: dashboard
---

## Inputs {.sidebar}

{{< brand logo icon >}}

Or, you could use the shortcode to set the background of a revealjs slide to your primary brand color:

slides.qmd
---
format: revealjs
---

## Slide Title {background-color='{{< brand color primary >}}'}
WarningLimitation

You can’t currently access typography, meta, or defaults values using the brand shortcode.

In SCSS

The colors defined in palette are set as SCSS variables of the form brand-COLOR_NAME. For example, if _brand.yml defines blue:

_brand.yml
color:
  palette:
    blue: "#ddeaf1"

Then the variable $brand-blue is will be set to #ddeaf1 in the defaults layer of Quarto’s SCSS layering system. You can add a custom SCSS file, styles.scss, in the usual way:

_quarto.yml
format:
  html:
    theme: [styles.scss]

Then styles.scss can use these brand variables to make style tweaks. For example, you might want all h1 elements to be blue:

styles.scss
/*-- scss:rules --*/

h1 {
  color: $brand-blue;
}

When you specify SCSS files without an explicit brand element, it is equivalent to listing them after brand. For instance, the above theme is equivalent to:

_quarto.yml
format:
  html:
    theme: [brand, styles.scss]

The order of elements in theme controls their priority. For example, you could layer brand and your custom SCSS on top of a built-in theme:

_quarto.yml
format:
  html:
    theme: [cosmo, brand, styles.scss]

You can learn more about layering themes in More About Quarto Themes.

Typst

In Typst documents, brand colors are set in a dictionary called brand-color. You can access them directory in raw Typst blocks using the syntax brand-color.COLOR_NAME. For example, you could make a rectangle filled with your primary brand color:

document.qmd

```{=typst}
#rect(fill: brand-color.primary)
```

Brand logos are set in dictionaries called brand-logo and brand-logo-images.

For example, you can write Typst code to insert an image using its resolved path and alt text from brand.logo.images:

document.qmd
---
format: typst
brand:
  logo:
    images:
      custom:
        path: custom.png
        alt: custom logo
---

```{=typst}
#image(brand-logo-images.custom.path, alt=brand-logo-images.custom.alt)
```

Lua API

Filters and shortcodes can access brand values using the brand Lua module.

local brand = require('modules/brand/brand')
local primary = brand.get_color('primary')

Sharing brands across projects

Organizations often maintain a shared brand that multiple projects should use. The q2 use brand command brings an external brand into your project. (Quarto 1 also supports brand extensions; those are not yet supported in Quarto 2 — see below.)

Warning

Quarto requires all brand assets—including logos and font files—to live within your project directory. q2 use brand copies brand files into your project rather than referencing them externally.

In most cases, these assets should be committed to source control.

Adding a brand with q2 use brand

q2 use brand puts a brand in your project and declares it in _quarto.yml. Both halves matter: without the brand: key, the files would land on disk and change nothing about how your project renders.

With no source, it writes a starter _brand.yml you can edit:

Terminal
q2 use brand
Added a brand to /path/to/project:

  created          _brand.yml
  updated          _quarto.yml

With a source, it copies that brand instead. A source can be a local path, a GitHub repository, or the URL of a .tar.gz or .zip archive:

Terminal
q2 use brand ./path/to/brand
q2 use brand myorg/shared-brand
q2 use brand myorg/shared-brand@v2.1.0
q2 use brand myorg/monorepo/brands/dark
q2 use brand https://example.com/brand.tar.gz

A GitHub source may name a tag or branch with @<ref>, and a subdirectory within the repository. With no @<ref>, Quarto looks for a main branch and then a master branch.

Where the brand lands

  • A source that is just a brand file goes to _brand.yml in your project root, and _quarto.yml gets brand: _brand.yml.
  • A source that also carries logos or font files goes to _brand/, so those assets do not scatter across your project root. _quarto.yml then gets brand: _brand/_brand.yml.

Either way the command tells you what it wrote and what it declared.

Quarto will not overwrite your work

q2 use brand refuses, without writing anything, if:

  • there is no _quarto.yml (it will not create one — use q2 create project default . first);
  • your project already has a _brand.yml or _brand.yaml;
  • your _quarto.yml already declares a brand:.

Each refusal names what it found and where. Running the command a second time is therefore an error rather than a silent no-op — if you meant to replace an existing brand, say so with --force.

Previewing changes

--dry-run reports the full plan, including the _quarto.yml edit, and writes nothing:

Terminal
q2 use brand --dry-run
(dry run) would add a brand to /path/to/project:

  created          _brand.yml
  updated          _quarto.yml

(dry run) nothing was written.

Trusting a remote source

Downloading a brand runs someone else’s content through your machine, so Quarto asks before fetching from a URL or a GitHub repository. The default answer is no.

In a script, on CI, or with --json there is nobody to ask, and Quarto refuses rather than proceeding. Pass --trust to confirm in advance:

Terminal
q2 use brand myorg/shared-brand --trust

A dry run of a remote source still downloads it to build the plan, so it needs the same trust. In a terminal, q2 use brand <source> --dry-run asks before it downloads. In a script, pass --trust with --dry-run:

Terminal
q2 use brand myorg/shared-brand --dry-run --trust --no-prompt
Note--force and --trust are different permissions

--force lets Quarto overwrite your own files: an existing brand file, or an existing brand: declaration.

--trust lets Quarto download someone else’s content without asking.

Neither implies the other, deliberately. A script that needs to replace a local brand should not thereby gain permission to execute whatever a URL serves.

The two flags also differ under --dry-run. A dry run downloads but never overwrites, so --trust combines with --dry-run and --force does not.

Non-interactive usage

For scripts, combine the flags you need with --no-prompt, or use --json for machine-readable output:

Terminal
q2 use brand myorg/shared-brand --trust --json

--json writes exactly one result object on stdout and sends diagnostics to stderr as JSON lines:

{"version":1,"path":"/path/to/project","dry_run":false,
 "files":[{"path":"_brand.yml","action":"created"},
          {"path":"_quarto.yml","action":"updated"}]}

Quarto Brand Extensions

Quarto 1 can also distribute a brand as an extension — a repository with an _extension.yml declaring contributes.metadata.project.brand, installed into _extensions/.

WarningNot supported in Quarto 2

Quarto 2 has no extension system yet, so q2 use brand cannot install a brand extension. Pointed at one, it says so and names the brand file inside it, which you can copy into your project by hand:

Terminal
q2 use brand myorg/brand-extension
Error: myorg/brand-extension is a Quarto 1 brand extension
It declares its brand as `contributes.metadata.project.brand: acme.yml` in an
_extension.yml. Quarto 2 has no extension system yet, so `q2 use brand` cannot
install it.

You can still use the brand by hand: copy acme.yml into your project as
_brand.yml and add `brand: _brand.yml` to _quarto.yml.

Combining brands and themes

Note

The following information is only necessary if you want to combine bootswatch themes with _brand.yml.

Migrating existing projects to Quarto 1.6’s _brand.yml support is a straightforward process. The usual way to create themes in Quarto 1.5 and earlier is to use one of the predefined bootswatch themes. This is often combined with an additional user-defined .scss file. In Quarto 1.5, a _quarto.yml file usually has an entry like the following:

# Quarto 1.5 syntax
theme:
  - cosmo       # a predefined bootswatch theme
  - tweaks.scss # a user-defined customization

When using this syntax with Quarto 1.6’s _brand.yml support, keep in mind that _brand.yml always takes lowest priority in styles. In other words, the configuration above is equivalent to the following:

# Quarto 1.6 syntax
theme:
  - brand        # theming derived from `_brand.yml`
  - cosmo        # a predefined bootswatch theme
  - tweaks.scss  # a user-defined customization

As a result, values set by brand here are potentially overriden by the cosmo theme or by tweaks.scss. This is sometimes useful, but often you will want to make brand more important than the theme. For these situations, use the following:

# Quarto 1.6 syntax
theme:
  - cosmo        # a predefined bootswatch theme
  - brand        # theming derived from `_brand.yml`
  - tweaks.scss  # a user-defined customization

The analogous syntax also works for combining light and dark brands with light and dark themes:

# Quarto 1.7 syntax
theme:
  light:
    - cosmo
    - brand
  dark:
    - slate
    - brand

Learn more about how Quarto generates styles in More About Quarto Themes.