Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature suggestion: map (additional) Yaml variables to CSS :root #5982

Open
baptiste opened this issue Jun 20, 2023 · 5 comments
Open

Feature suggestion: map (additional) Yaml variables to CSS :root #5982

baptiste opened this issue Jun 20, 2023 · 5 comments
Assignees
Labels
enhancement New feature or request themes Related to HTML theming or any other style related issue (like highlight-style)
Milestone

Comments

@baptiste
Copy link

baptiste commented Jun 20, 2023

Description

I'm suggesting that it could be useful to map a few additional CSS variables from Yaml to the CSS :root variables. Currently, there are already some variables defined such as:

:root {
--quarto-body-bg: #ffffff;
--quarto-body-color: #212529;
--quarto-text-muted: #6c757d;
--quarto-border-color: #dee2e6;
--quarto-border-width: 1px;
--quarto-border-radius: 0.25rem;

--quarto-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

and, for example, the document's fontcolor, monofont, linkcolor, etc, can be set in the Yaml. I believe it would be useful to add a couple of such mappings, for example to define a "accent" / "highlighting" colour, as a minimal theming system. It's common for a document to have one main colour (black font), and another colour for titles, buttons, etc. This kind of logic is used in other systems, such as Beamer themes or ggplot2 themes. Colour palettes can even be derived from this parent element by CSS transformations, e.g.

color: color-mix(in srgb, var(--quarto-highlight) 20%, transparent);

to create a semi-transparent, lighter shade.

I'm not sure how many of these mappings might make sense – presumably just very few, otherwise it'll get too complicated to follow the possible interactions between Bootstrap and (S)CSS variables.

@baptiste baptiste changed the title Feature suggestion Feature suggestion: map some Yaml variables to CSS :root Jun 20, 2023
@baptiste baptiste changed the title Feature suggestion: map some Yaml variables to CSS :root Feature suggestion: map (additional) Yaml variables to CSS :root Jun 20, 2023
@baptiste
Copy link
Author

For reference, the original discussion here:

Originally posted by @baptiste in #5959

Here's a situation I encountered today:

I have a custom Html template, say for Gandalf's resumé,

Screenshot 2023-06-18 at 19 35 26

and I wish to define the font colours in the Yaml header with something like:

fontcolor: "#606060"
highlightcolor: "#8a1313"

where the fontcolor follows the standard Quarto convention, but I could not find a built-in way to specify other colours, such as the "highlight" / "accent" (red, in this case). Changing this colour in the Yaml (and nowhere else) lets me get a different style:

Screenshot 2023-06-18 at 20 13 41

Pandoc variables cannot be inserted into my custom CSS file (defining <h1>, etc.), but I figured I could inject this custom Yaml variable indirectly by referring to CSS variables:

h1 {
  text-transform: uppercase;
    font-weight: 700;
    color: var(--quarto-highlight);
}

and defining the variable in a custom template partial (where pandoc variables can be injected):

  <style type="text/css">
    :root {
      --quarto-highlight: $highlightcolor$;
    }
  </style>

I came to this from a similar workaround in Latex (with macros instead of CSS variables).

@cscheid cscheid self-assigned this Jun 20, 2023
@cscheid cscheid added the enhancement New feature or request label Jun 20, 2023
@cscheid cscheid added this to the v1.4 milestone Jun 20, 2023
@cscheid
Copy link
Collaborator

cscheid commented Jun 20, 2023

Thanks, this is very helpful.

I don't know when we'll get to it, but at some point we have to make all of the theming options in quarto fit well together, and you've found an important aspect.

@cscheid cscheid modified the milestones: v1.4, v1.5 Dec 12, 2023
@cscheid cscheid added the themes Related to HTML theming or any other style related issue (like highlight-style) label Feb 26, 2024
@cscheid cscheid modified the milestones: v1.5, Future Feb 26, 2024
@alex-r-bigelow
Copy link

I don't know when we'll get to it, but at some point we have to make all of the theming options in quarto fit well together, and you've found an important aspect.

(A comment from a lurker, mostly to add to—and maybe complicate, sorry 😬—that discussion, if/when it happens...)

TL;DR: It'd be really helpful if there were ONE source of truth for theming, whether it's CSS variables (my preference), YAML settings, or SASS variables.

My use case, context

I'm trying to use Quarto for the docs of an existing Vite project, that already has a variables.css file with very similar foreground / background CSS variables as Quarto's settings.

It'd be amazing (though impossible for a lot of reasons) if I could just point Quarto to that file, ... but it's doing all kinds of runtime light-dark() CSS magic, as well as overriding variables based on selectors, and I recognize that Quarto takes more of a compile-time approach to theming.

The first thing I tried was a hack like $body-bg: unquote('var(--background-color)');, which of course failed:

Error: $color: var(--background-color) is not a color.
    ╷
984 │   $red: _linear-channel-value(quarto-color.red($color));

Not sure how important things like that are for Quarto to do at compile time, but ... changing that approach might be a lower-effort way to make Quarto work with CSS variables?

The correct thing for my project is probably to convert my variables.css file for colors from CSS to SASS, so that both the app and the docs can refer to the base colors, even if the Vite app continues to play wild CSS runtime games with the generated values internally, and I have to set up the Quarto theming separately.

But for ... more time than I'd like to admit..., I seriously considered writing a script to generate custom light/dark Bootswatch themes for Quarto, based on the Vite project's root CSS variables, mostly so I could stop worrying about where Quarto wants me to configure each color (and to avoid configuring SASS as a dependency to the Vite project, just for one file).

Support for modern CSS runtime things like light-dark() would be nice, but that's definitely less important than solving the issue of needing to consult Quarto's docs every time I want to update a color, to figure out whether it should be a setting in _branding.yml, a variable override underneath the /*-- scss:defaults --*/ comment in a theme-tweaks.scss file, a page-specific setting in its front matter, or overriding Bootstrap things directly with CSS.

@cscheid
Copy link
Collaborator

cscheid commented Feb 19, 2025

@alex-r-bigelow ( 👋 ) can you give us a concrete example of where this

mostly so I could stop worrying about where Quarto wants me to configure each color (and to avoid configuring SASS as a dependency to the Vite project, just for one file).

is hitting you? It's hard for us to consider improvements without a concrete situation to consider.

@alex-r-bigelow
Copy link

alex-r-bigelow commented Feb 26, 2025

Sorry for the delay; admittedly, I'm still a fairly casual / semi-new Quarto user, so it's taken a moment to identify the right words.

I'm including a way-too-detailed dump to help communicate the concrete situation of where/how I got stuck, but TL;DR:

  1. My first attempt was a mess
  2. The docs could use some improvement; I've opened a PR
  3. Are there docs for exposed CSS variables, based on _brand.yml / _quarto.yml / SCSS settings?
  4. This feels like an interesting vis problem

If this is way too much information, not enough information, something is confusing, and/or a helper* would be useful for any of this ... I'm always happy to meet up or hop on a call.

* Ugh, sorry for the unsolicited ad. but in case it's relevant: I'm still an under-employed vis freelancer...


1. Where I Went Wrong

An example that sent me down a bad path: trying to set these two things at the same time:

  • page background color
  • navbar color

Attempting to follow the HTML Theming docs—where Google landed me first [2]—step-by-step, I ended up creating this mess:

quarto-site/_quarto.yml
format:
  html:
    backgroundcolor: "#e9e9e9"
    mainfont: "Raleway"
    theme:
      - minty
      - quartoTweaks.scss
    css: built-library/style.css
quarto-site/quartoTweaks.scss
/*-- scss:defaults --*/

/*
THESE COLORS ARE MANUALLY COPIED
FROM src/core-styles/variables.scss

If you change a color here, please
also update it there
*/

$cb-extra-dark-1-teal: #0e4c32;
$cb-extra-dark-2-orange: #6f200e;
$cb-extra-dark-3-purple: #302d59;
$cb-extra-dark-4-pink: #780e3f;
$cb-extra-dark-5-green: #25500e;
$cb-extra-dark-6-yellow: #77530e;
$cb-extra-dark-7-brown: #50310e;
$cb-extra-dark-8-grey: #252525;

$cb-dark-1-teal: #00744c;
$cb-dark-2-orange: #aa2d00;
$cb-dark-3-purple: #494389;
$cb-dark-4-pink: #b70060;
$cb-dark-5-green: #377b00;
$cb-dark-6-yellow: #b68000;
$cb-dark-7-brown: #7b4a00;
$cb-dark-8-grey: #373737;

$cb-1-teal: #1b9e77;
$cb-2-orange: #d95f02;
$cb-3-purple: #7570b3;
$cb-4-pink: #e7298a;
$cb-5-green: #66a61e;
$cb-6-yellow: #e6ab02;
$cb-7-brown: #a6761d;
$cb-8-grey: #666666;

$cb-light-1-teal: #66c2a5;
$cb-light-2-orange: #fc8d62;
$cb-light-3-purple: #8da0cb;
$cb-light-4-pink: #e78ac3;
$cb-light-5-green: #a6d854;
$cb-light-6-yellow: #ffd92f;
$cb-light-7-brown: #e5c494;
$cb-light-8-grey: #b3b3b3;

$cb-extra-light-1-teal: #b3e2cd;
$cb-extra-light-2-orange: #fdcdac;
$cb-extra-light-3-purple: #cbd5e8;
$cb-extra-light-4-pink: #f4cae4;
$cb-extra-light-5-green: #e6f5c9;
$cb-extra-light-6-yellow: #fff2ae;
$cb-extra-light-7-brown: #f1e2cc;
$cb-extra-light-8-grey: #cccccc;

$my-extra-black: #050505;
$my-black: #0e0e0e;
$my-off-black: #212121;
$my-mid-soft-black: #333333;
$my-soft-black: #4f4f4f;
$my-middle-grey: #666666;
$my-soft-white: #afafaf;
$my-mid-soft-white: #b3b3b3;
$my-off-white: #dddddd;
$my-white: #e9e9e9;
$my-extra-white: #ffffff;

/*
This stuff was copied from the minty theme's source code:

https://github.com/thomaspark/bootswatch/blob/v5/dist/minty/_variables.scss

We don't have an override for blue or indigo; for now we're just leaving
those lines verbatim for reference
*/

$blue: #007bff !default;
$indigo: #6610f2 !default;
$purple: $cb-3-purple !default;
$pink: $cb-4-pink !default;
$red: $cb-2-orange !default;
$orange: $cb-light-2-orange !default;
$yellow: $cb-6-yellow !default;
$green: $cb-5-green !default;
$teal: $cb-1-teal !default;

$primary: $teal !default;
$secondary: $purple !default;

/*
Note that the page background color is set in `_quarto.yml`;
otherwise we'd have to override minty's $white variable here
*/

/*-- scss:rules --*/

.navbar {
  /*
  Normally, this is set via $primary, but we want the navbar to be a little
  different, so we override with a slightly darker version of the same color.
  Note that this refers to a CSS variable, not one of the above SASS variables,
  because SASS variables aren't exposed (for this to work, we need to make
  sure that built-library/style.css is imported correctly)
  */
  background-color: var(--cb-dark-1-teal);
}
src/core-styles/variables.css
:root {
  /*
  THESE COLORS ARE MANUALLY COPIED IN
  quarto-site/quartoTweaks.scss

  If you update a color here, make sure
  to also update it there
  */

  /* Colorbrewer 8 extended colors: */
  --cb-extra-dark-1-teal: #0e4c32;
  --cb-extra-dark-2-orange: #6f200e;
  --cb-extra-dark-3-purple: #302d59;
  --cb-extra-dark-4-pink: #780e3f;
  --cb-extra-dark-5-green: #25500e;
  --cb-extra-dark-6-yellow: #77530e;
  --cb-extra-dark-7-brown: #50310e;
  --cb-extra-dark-8-grey: #252525;

  --cb-dark-1-teal: #00744c;
  --cb-dark-2-orange: #aa2d00;
  --cb-dark-3-purple: #494389;
  --cb-dark-4-pink: #b70060;
  --cb-dark-5-green: #377b00;
  --cb-dark-6-yellow: #b68000;
  --cb-dark-7-brown: #7b4a00;
  --cb-dark-8-grey: #373737;

  --cb-1-teal: #1b9e77;
  --cb-2-orange: #d95f02;
  --cb-3-purple: #7570b3;
  --cb-4-pink: #e7298a;
  --cb-5-green: #66a61e;
  --cb-6-yellow: #e6ab02;
  --cb-7-brown: #a6761d;
  --cb-8-grey: #666666;

  --cb-light-1-teal: #66c2a5;
  --cb-light-2-orange: #fc8d62;
  --cb-light-3-purple: #8da0cb;
  --cb-light-4-pink: #e78ac3;
  --cb-light-5-green: #a6d854;
  --cb-light-6-yellow: #ffd92f;
  --cb-light-7-brown: #e5c494;
  --cb-light-8-grey: #b3b3b3;

  --cb-extra-light-1-teal: #b3e2cd;
  --cb-extra-light-2-orange: #fdcdac;
  --cb-extra-light-3-purple: #cbd5e8;
  --cb-extra-light-4-pink: #f4cae4;
  --cb-extra-light-5-green: #e6f5c9;
  --cb-extra-light-6-yellow: #fff2ae;
  --cb-extra-light-7-brown: #f1e2cc;
  --cb-extra-light-8-grey: #cccccc;

  --my-extra-black: #050505;
  --my-black: #0e0e0e;
  --my-off-black: #212121;
  --my-mid-soft-black: #333333;
  --my-soft-black: #4f4f4f;
  --my-middle-grey: #666666;
  --my-soft-white: #afafaf;
  --my-mid-soft-white: #b3b3b3;
  --my-off-white: #dddddd;
  --my-white: #e9e9e9;
  --my-extra-white: #ffffff;

  --hard-background-color: light-dark(
    var(--my-extra-white),
    var(--my-extra-black)
  );
  --background-color: light-dark(var(--my-white), var(--my-black));
  --mid-soft-background-color: light-dark(
    var(--my-mid-soft-white),
    var(--my-mid-soft-black)
  );
  --soft-background-color: light-dark(
    var(--my-soft-white),
    var(--my-soft-black)
  );
  --separator-color: var(--my-middle-grey);
  --soft-foreground-color: light-dark(
    var(--my-soft-black),
    var(--my-soft-white)
  );
  --mid-soft-foreground-color: light-dark(
    var(--my-mid-soft-black),
    var(--my-mid-soft-white)
  );
  --foreground-color: light-dark(var(--my-black), var(--my-white));
  --hard-foreground-color: light-dark(
    var(--my-extra-black),
    var(--my-extra-white)
  );

  /* default accent color is teal */
  --accent-color-extra-dark: var(--cb-extra-dark-1-teal);
  --accent-color-dark: var(--cb-dark-1-teal);
  --accent-color: var(--cb-1-teal);
  --accent-color-light: var(--cb-light-1-teal);
  --accent-color-extra-light: var(--cb-extra-light-1-teal);

  --accent-color-extra-fg: light-dark(
    var(--accent-color-extra-dark),
    var(--accent-color-extra-light)
  );
  --accent-color-fg: light-dark(
    var(--accent-color-dark),
    var(--accent-color-light)
  );
  --accent-color-bg: light-dark(
    var(--accent-color-light),
    var(--accent-color-dark)
  );
  --accent-color-extra-bg: light-dark(
    var(--accent-color-extra-light),
    var(--accent-color-extra-dark)
  );
}

/*
Not bothering with the whole file, but an example of how the Vite
app overrides CSS variables by assigning a class
*/
.orange {
  --accent-color-extra-dark: var(--cb-extra-dark-2-orange);
  --accent-color-dark: var(--cb-dark-2-orange);
  --accent-color: var(--cb-2-orange);
  --accent-color-light: var(--cb-light-2-orange);
  --accent-color-extra-light: var(--cb-extra-light-2-orange);

  --accent-color-extra-fg: light-dark(
    var(--accent-color-extra-dark),
    var(--accent-color-extra-light)
  );
  --accent-color-fg: light-dark(
    var(--accent-color-dark),
    var(--accent-color-light)
  );
  --accent-color-bg: light-dark(
    var(--accent-color-light),
    var(--accent-color-dark)
  );
  --accent-color-extra-bg: light-dark(
    var(--accent-color-extra-light),
    var(--accent-color-extra-dark)
  );
}
quarto-site/built_library/style.css
/*
This file is definitely beyond anything that Quarto should worry about;
just including it for context.

My Vite app has its own button components, and I want to use the same
styling for buttons in the Quarto site... so I have a script that builds a
"component library" version of the Vite app, really just to generate a `style.css`
file for Quarto to import.

In practice, this file is minified and has more UI stuff beyond buttons, but
the original, un-minified CSS is along these lines:
*/
@import url("../../core-styles/variables.css");

.origraph-button-wrapper {
  display: flex;
  gap: 0.125em;
}

.origraph-button {
  display: flex;
  flex-direction: row;
  align-items: center;
  flex-wrap: nowrap;
  gap: 0.25em;
  text-decoration: none;
  padding: 0.5em 0.75em 0.5em 0.75em;
  border-radius: 2em;
  line-height: 1em;
  border: none;
  outline: none;
  outline-offset: -2px;
  cursor: pointer;
  font-family: var(--header-font);
  white-space: nowrap;
  font-weight: 600;
  user-select: none;

  &:focus-visible {
    outline: none;
    box-shadow: 0 0 10px 2px var(--soft-background-color);
  }

  &.splitLeft {
    padding-left: 0.25em;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    justify-content: flex-end;
  }
  &.splitRight {
    padding-right: 0.25em;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    justify-content: flex-start;
  }
  &.singleIconButton {
    padding: 0.5em 0.5em;
  }

  .shortcutHint {
    text-transform: uppercase;
    letter-spacing: 0.35ex;
    font-size: 0.5em;
  }
  .gap {
    flex-grow: 1;
  }

  .origraph-icon {
    color: var(--background-color);
    &.useMask {
      background-color: var(--background-color);
    }
  }

  /* Unless otherwise-classed, buttons will default to the teal accent */
  color: var(--background-color);
  background-color: var(--accent-color);
  transition: all 0.2s ease-in-out;
  &.active {
    color: var(--background-color);
    background-color: var(--accent-color-fg);
  }
  &:focus,
  &:hover {
    color: var(--background-color);
    background-color: var(--accent-color-extra-fg);
    box-shadow: 0px 0px 70px 3px var(--accent-color-extra-bg);
  }
  &.minimal {
    color: var(--accent-color);
    .origraph-icon {
      color: var(--accent-color);
      &.useMask {
        background-color: var(--accent-color);
      }
    }
    background-color: transparent;
    outline: 2px solid var(--accent-color);
    &.active {
      color: var(--accent-color-fg);
      .origraph-icon {
        color: var(--accent-color-fg);
        &.useMask {
          background-color: var(--accent-color-fg);
        }
      }
    }
    &:focus,
    &:hover {
      color: var(--accent-color-extra-fg);
      .origraph-icon {
        color: var(--accent-color-extra-fg);
        &.useMask {
          background-color: var(--accent-color-extra-fg);
        }
      }
      outline: 2px solid var(--accent-color-extra-fg);
    }
  }
}

This setup feels very wrong (turns out [2], it is!), especially w.r.t.:

  1. needing to read + copy + paste + hack + debug minty's source code, just to discover $primary's relevance for the navbar color
  2. the navbar color setting living so far away from backgroundcolor

My first workaround attempt looked like:

# _quarto.yml
format:
  html:
    theme:
      - variables.css
      - brand

# _brand.yml
color:
  background: "var(--my-white)"
  primary: "var(--cb-dark-1-teal)"

... resulting in this error:

Error: $color: var(--my-white) is not a color.
    ╷
984 │   $red: _linear-channel-value(quarto-color.red($color));
    │                               ^^^^^^^^^^^^^^^^^^^^^^^^

2. Misunderstood / ignored _brand.yml

Somehow, I missed that _brand.yml was a whole, cool project of its own.

This is what my previous comment—wishing for "ONE source of truth for theming"—was looking for; I just didn't realize that it already existed.

Think-aloud notes from trying to navigate the docs
  • There are no links or mentions from HTML Theming docs, to branding
    • There IS an indirect way to discover branding from this page, but first you have to go all the way through the details of SCSS layering details. By the time you've read about and tried things involving special SASS comment strings, it feels like you're so deep in the weeds that the last thing on an Advanced page must be a last resort for the desperate, not the simplest / most basic / best way
  • The Basic options section was especially distracting; most of the HTML Theming page is about SASS variables, applied to the whole site. But this specific section is about YAML front matter, applied to individual pages. Instead of looking for "is there a better way to set basic options for all formats," I went down rabbit holes like: ...
    • Do I need to set backgroundcolor in every page's YAML front matter, or is this something that would work site-wide in _quarto.yml? That works, but I have to do an experiment to discover that it does
    • With backgroundcolor as a "Basic option," does that mean that there's an implicit best practice to use YAML to set that, even if I'm also messing with other page colors like the navbar elsewhere?
    • Can I set one of those linked 1,400 SASS variables, via YAML? As far as I can tell, no, you can't override something like $primary from YAML 👈 Leftover from the earliest version of this comment, before I re-discovered that _brand.yml was even a thing
    • Oh, you CAN override ... some of those SASS variables ... in a different file (_brand.yml), with slightly different variable names [4], and the full spec is not yet supported (by "full spec," does that mean the 1,400 SASS variables? A bigger / smaller set?) 👈 Also a leftover comment, before I realized that _brand.yml was its own project
  • I'd definitely encountered _brand.yml before (misspelled it in the last comment on this issue as branding.yml, so I knew it existed!)... but clearly I didn't investigate it closely enough to understand what it was.
    • I think my most recent encounter with brand settings was in the context of using quarto to make some quick revealjs slides a few weeks ago. This was probably a perfect storm of bad timing; attempts to use brand.yml weren't successful then (because I didn't realize how recently _brand.yml support was added, and I was on Quarto v1.5.57!), so I ended up hacking the CSS directly, ... it's possible that, this time, I was engaging in not-quite-conscious avoidant behavior—and it took me a few days to realize that it 1. was new, 2. it was its own thing, and 3. that I was on an already-old version of Quarto.
    • To brand-new eyes, the orange "Limitation" warnings under the branding docs—especially after reading two other theming docs pages—make it feel like "this is a deprecated way to do Quarto theming," ... even though it's the other way around! Maybe all it would take would be a more attention-grabbing header / teaser logo to highlight that it's a shiny new thing, that's not just part of Quarto?

I've made a PR with some suggestions to make my mistakes less likely, but feel free to disregard—I might just be an odd duck who cruises too quickly through documentation, and things that are obvious to other people often fly right over my head.

With Quarto updated and _brand.yml working, a better setup for my project looks like:

quarto-site/_quarto.yml
format:
  html:
    theme:
      - minty
      - brand
    css:
      - built-library/style.css
      - quartoTweaks.css
quarto-site/_brand.yml
typography:
  fonts:
    - family: Raleway
      source: google
  base: Raleway
  headings: Raleway

color:
  palette:
    # THESE COLORS ARE MANUALLY COPIED
    # FROM src/core-styles/variables.scss

    # If you change a color here, please
    # also update it there

    cb-extra-dark-1-teal: "#0e4c32"
    cb-extra-dark-2-orange: "#6f200e"
    cb-extra-dark-3-purple: "#302d59"
    cb-extra-dark-4-pink: "#780e3f"
    cb-extra-dark-5-green: "#25500e"
    cb-extra-dark-6-yellow: "#77530e"
    cb-extra-dark-7-brown: "#50310e"
    cb-extra-dark-8-grey: "#252525"

    cb-dark-1-teal: "#00744c"
    cb-dark-2-orange: "#aa2d00"
    cb-dark-3-purple: "#494389"
    cb-dark-4-pink: "#b70060"
    cb-dark-5-green: "#377b00"
    cb-dark-6-yellow: "#b68000"
    cb-dark-7-brown: "#7b4a00"
    cb-dark-8-grey: "#373737"

    cb-1-teal: "#1b9e77"
    cb-2-orange: "#d95f02"
    cb-3-purple: "#7570b3"
    cb-4-pink: "#e7298a"
    cb-5-green: "#66a61e"
    cb-6-yellow: "#e6ab02"
    cb-7-brown: "#a6761d"
    cb-8-grey: "#666666"

    cb-light-1-teal: "#66c2a5"
    cb-light-2-orange: "#fc8d62"
    cb-light-3-purple: "#8da0cb"
    cb-light-4-pink: "#e78ac3"
    cb-light-5-green: "#a6d854"
    cb-light-6-yellow: "#ffd92f"
    cb-light-7-brown: "#e5c494"
    cb-light-8-grey: "#b3b3b3"

    cb-extra-light-1-teal: "#b3e2cd"
    cb-extra-light-2-orange: "#fdcdac"
    cb-extra-light-3-purple: "#cbd5e8"
    cb-extra-light-4-pink: "#f4cae4"
    cb-extra-light-5-green: "#e6f5c9"
    cb-extra-light-6-yellow: "#fff2ae"
    cb-extra-light-7-brown: "#f1e2cc"
    cb-extra-light-8-grey: "#cccccc"

    my-extra-black: "#050505"
    my-black: "#0e0e0e"
    my-off-black: "#212121"
    my-mid-soft-black: "#333333"
    my-soft-black: "#4f4f4f"
    my-middle-grey: "#666666"
    my-soft-white: "#afafaf"
    my-mid-soft-white: "#b3b3b3"
    my-off-white: "#dddddd"
    my-white: "#e9e9e9"
    my-extra-white: "#ffffff"

    # Stuff that actually applies my
    # colors to the quarto site:

    purple: cb-3-purple
    pink: cb-4-pink
    red: cb-dark-2-orange
    orange: cb-2-orange
    yellow: cb-6-yellow
    green: cb-5-green
    teal: cb-1-teal
  primary: teal
  secondary: purple
  success: green
  info: pink
  warning: yellow
  danger: red
  foreground: my-black
  background: my-white
quarto-site/quartoTweaks.css
.navbar {
  /*
  This is still a little awkward, and still needs my built-library/style.css
  import hack, but it's better / less confusing now that the theme is defined
  with YAML instead of SASS variables
  
  Additionally, this avoids all of my worries about getting special
  /*-- scss:something *--/ comments wrong
  */
  background-color: var(--cb-dark-1-teal);
}
src/core-styles/variables.css

(unchanged, except for the comment pointing to quarto-site/_brand.yml)

quarto-site/built_library/style.css

(unchanged)

This setup could still probably be cleaner, and still involves guesswork [4], but _brand.yml at least helped me worry less about how minty's internals might be affecting what I'm trying to do, what's going on inside all the SASS compilation, what kind of magic is going on with all those /*-- scss:something *--/ sections, etc.

3. Referencing _brand.yml settings from CSS?

My use case is, admittedly, pretty strange: using Quarto inside another project.

@baptiste's suggestion—if I understand it correctly—to expose settings as CSS variables is probably a better approach than supporting hacks like background: var(--my-white) in YAML. Poking around in devtools, it looks like YAML (and SASS?) variables are already exposed with a --quarto-scss-export- prefix? For example, with my quarto-site/_brand.yml settings above, I'm seeing variables like this:

--quarto-scss-export-brand-teal: #1b9e77;
--quarto-scss-export-primary: #1b9e77;

... but I'm not sure if they're documented anywhere? I kinda would have expected a -brand- before primary, as that's also a _brand.yml setting? Or, conversely, a -palette- before teal, if it's based on the YAML structure?

Without documentation, I'd worry that they're temporary / prone to renaming... but otherwise, they'd be something that I'd try to use, instead of my weird generated built-library/style.css hack.

4. Maybe a tool could help?

I'm probably both preaching to the choir, and over-simplifying the ultimate goals of this cool thing called Positron that ... somebody ... is working on... but in the event that you need further justification from an external person for why vis matters:

The dependency graph of Quarto's theme settings, across:

  • separate files,
  • config formats (YAML, SCSS, CSS, etc),
  • output contexts (html, typst, revealjs, etc),
  • and similar-but-different variable names / structures (e.g. backgroundcolor: vs color: background:),

...amounts to very complex data.

For simple, clear tasks—i.e. basic theme settings like background and primary that are generalizable across most output formats—_brand.yml is a perfect solution. To me, it feels like it lives in the top-right "Algorithm Automation Possible" corner of Figure 1 in the DSM Paper.

However, for more complex, fuzzy tasks—like trying to debug "why isn't my navbar color updating?" or "what are all the things that will be affected by messing with primary?" it feels like something is still missing.

Websites have developer tools for debugging CSS, but for Quarto, they break down as soon as you hit parts of the graph that live beyond CSS. For example, even in an html-only context: trying to debug the navbar color that minty is setting, all you see in the browser's devtools is this dead end:

/* bootstrap-d0b73ff65d5a0d883de95af7fbbe1a1c.min.css */
.navbar {
  background-color: #78c2ad;
}

Yes, we can override that with CSS directly, but that prompts a list of worries in my head, that a visualization might be able to help with:

Vis tasks

Selfish sample size of one user... happy to collect a more data-informed task list if it'd be helpful

  • From a design perspective:
    • Where else is that color being used?
    • Might my navbar color choice clash with some future edit, using a Quarto thing that I'm not thinking about right now, that doesn't even exist in my site yet?
    • How to predict whether I should be considering the color of other things, in addition to the navbar?
  • From a technical perspective:
    • If the page takes a moment to load my CSS override, might that flicker?
    • Since this looks like a bootstrap thing, maybe I should be overriding some kind of higher-level variable?
    • How to discover those variables?
      • Documentation? Quarto's? Bootstrap's? (Turns out, the correct answer was _brand.yml's, but it could have been somewhere else)
      • Read minty's source code?
      • Dive into that scary list of bootstrap's 1,400 SCSS variables?
  • Assuming that I find a higher-level, non-CSS thing that I want to override, where is the best place to do it? _quarto.yml? Per-page front matter? A quartoTweaks.scss file?
    • If _brand.yml currently supports what I want to change, that's wonderful. For other things, it feels like I should be leaving TODO: move this this to _brand.yml if/when it's eventually supported comments everywhere?
  • If, someday, I want to create PDFs from this project via typst, how can I be confident that I'm not going too high in the dependency tree (for technical or design reasons), accidentally changing the wrong setting that has unintended effects beyond html?
  • (Ultra-nerd perspective, that nobody but me will care about):
    • If bootstrap is doing math with my colors... I know, I know, it's probably not generating a color map for anything, but that still feels mildly scary. WHY is it doing color math, and should I worry about the color space through which it's interpolating / extrapolating?

It'd be really neat if we had something akin to Bootstrap theme generators (e.g. bootstrap.build/app) for Quarto, to help you:

  • understand a wider (full?) set of style and theme variables that exist across potential outputs (html, revealjs, typst, etc.), that may or may not yet have _brand.yml support
  • predict the extent of a potential change, both in terms of output, as well as specific element types
Some half-baked ideas; you probably already have something better cooking
  • Demo files like html-theme-test.qmd, revealjs-theme-test.qmd, etc., that you temporarily download and drop into your project, to see how your settings will affect a more comprehensive gallery of common Quarto content, than you might already have in your project?
    • More helpful versions of these demo files might even be able to do things like in-page color pickers / other dropdowns?
  • The metadata generated in .quarto/idx juxtaposed against window.getComputedStyle might be an opportunity:
    • to visualize beyond the current CSS dead ends in devtools; might be easy to make them part of *-theme-test.qmd files, or would also make sense as a browser / Positron extension?
    • Might be possible to add a feature that auto-saves WYSIWYG changes in the correct settings file?
    • Might also be a way to audit your current settings, to warn you "hey, just an FYI, _brand.yml just added support for this thing that you're setting via quartoTweaks.scss?"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request themes Related to HTML theming or any other style related issue (like highlight-style)
Projects
None yet
Development

No branches or pull requests

3 participants