Custom formatting of components in Quarto with divs
Motivation
I want to create custom styling for different components of a Quarto based (teaching) website. I know Quarto comes with callout blocks, which is similar to what I want. I was searching online for some information, and happened to come across my own blog post from about 2 years ago - aparently I previously had the same question and figured it out, but since then completely forgot 🙄.
As I was reading through my old post and looked at a few online sources, I decided that A) I was somewhat conceptually confused when I did the original blog post, and B) I needed things a bit tweaked. This new post are my notes on my latest thinking and attempt of styling.
Quarto callouts versus regular divs
In my opriginal post, I said I was making custom Quarto callouts. Turns out on further reflection, that’s not quite true. I was not actually using the callout machinery of Quarto.
It is possible to use the setup provided by Quarto to make new, custom callouts. But it seems too complicated to me. I did find a Quarto extension which makes this process easy. But I decided I wanted more flexibility. Using just regular divs, independent of the quarto callouts, seems to give me more flexibility and I’m not tied to whatever the good folks at Posit decide to do for the future of callouts.
Turns out that this is what I actually did in my previous post. I just defined new divs with SCSS/CSS, independent of Quarto callouts. But on revisiting my prior solution, I didn’t like the fact that I had to call the div with multiple nested levels. So here is a slightly updated approach to make things easier.
Improving custom divs
Previously, I came up with some SCSS/CSS code that I could use to get a layout I wanted, with a header and a body. But I had to call the div in my Quarto file like so:
:::{.goals}
::::{.goals-header}
Learning Goals
::::
::::{.goals-container}* Know how to make your own callouts.
* Be able to mess with some SCSS/CSS styling.
:::: :::
That worked, but having these multiple nested levels and labels was going to get tedious since I now wanted to wrap most sections of my text into their specific divs. Instead, I wanted to be able to call it like this:
::: {.goals}## Learning Goals
* Know how to make your own callouts.
* Be able to mess with some SCSS/CSS styling.
:::
That requires changing the SCSS/CSS. Unfortunately, I know very little about SCSS/CSS. Fortunately, we now have AI tools that seem to know a good bit. So I just fed ChatGPT my current version and told it what I wanted, and after a few iterations, I got it.
This is the updated SCSS/CSS code, including some helpful comments added by the AI. I renamed from goals
to newgoals
so my old blog post still works.
.newgoals {
margin: 1em 0;
border: 2px solid gray;
border-left: 10px solid teal;
border-radius: 10px;
background-color: white;
padding: 0; /* Ensure no unwanted padding */
}
/* Style the first child element (assumed to be the header) */
.newgoals > *:first-child {
margin: 0;
padding-top: 10px;
padding-right: 10px;
padding-bottom: 10px;
padding-left: 55px;
color: black;
background-color: rgb(123, 173, 173);
border-top-right-radius: 10px;
font-size: 1em;
font-weight: bold;
display: flex;
align-items: center; /* Vertically center the icon with text */
position: relative;
min-height: 45px; /* Ensures space for the icon */
/* Add the icon as a background image */
background-image: url("www/goal.png");
background-size: 35px auto; /* Ensures the image scales properly */
background-repeat: no-repeat;
background-position: 10px center; /* Adjust position */
}
/* Style the rest of the content */
.newgoals > *:not(:first-child) {
padding-top: 10px;
padding-left: 15px;
color: black;
background-color: white;
border-bottom-right-radius: 10px; }
Using your new callout
Well, it works. I can now write
::: {.newgoals}## Learning Goals
* Know how to make your own callouts.
* Be able to mess with some SCSS/CSS styling.
:::
to get
Learning Goals
- Know how to make your own callouts.
- Be able to mess with some SCSS/CSS styling.
I can now use that setup to define all kinds of divs (e.g. summary
, goals
, resources
, exercise
) that have a specific styling. And for further tweaks I’ll just ask some AI tool to do it for me (or at some time, I just end up learning enough SCSS/CSS by staring at it long enough, that it’s faster to write myself).
Summary
To sum it all up, here is what you need to do:
- If needed, create a new SCSS (or CSS) file and add the SCSS/CSS code chunks above to it.
- Edit your
_quarto.yml
file to include your new SCSS file. - Write
.qmd
documents using the fenced div (:::{}
) approach shown above. - Keep adding as many new styles as you want, and adjust them to however style you like.
Further resources
In my searches for how to do this, I found a nice course website and an associated slide deck. They ended up not helping me with this specific issue, but it contained some great material regarding styling in Quarto, and SCSS/CSS, etc.
Acknowledgments
As always, I rarely come up with completely new stuff, instead I cobble it together from other resources. The sources I cite above should obviously receive all the credit for the underlying ideas and explanations. And of course whatever resources the AI tool used (with or without permission) to help me update the SCSS/CSS.