- 3 Minutes Wednesdays
- Posts
- Keeping Quarto Themes Separate
Keeping Quarto Themes Separate
Guten Tag! š
Many greetings from Munich, Germany. Letās talk about my preferred way to manage brand styling in Quarto. Better yet, letās do so in very specific terms.
As you know, in the upcoming workshop weāre going build a monthly fund fact sheet for a fictional firm called BIRD Investment. Rendered to HTML, itās a clean report page:

The notable features of this can be seen but letās actually denote what we got:
logo in the top left corner,
firm name next to it in a bold serif font,
a short purple rule under the header,
purple headings everywhere, and
tables with alternating purple-tinted rows.
So what about the PDF output? Well, the exact same .qmd file produces this:

Look at this! Itās pretty darn close. So close, I just canāt resist to insert this meme here:

So how does that work under the hood? Well, there are actually two separate places where the brand values live, one for each output format.
On the HTML side, a theme.scss
declares the brand hex values (as SCSS variables)
creates the font stack and
plain CSS rules apply those variables to headings, links, and the custom header and table classes.

On the PDF side, typst-template.typ handles all of that.
It declares the same hex values and fonts again (this time as Typst constants):

It applies a handful of small Typst functions like
company-header()andcolored-text()
Notice what I did not say: I did not say thereās one magic brand file that both sides read from automatically. There isnāt. At least not in this demo.
The two declarations are kept in sync by hand. I do this on purpose so you can see exactly what each renderer needs and why.
What you get in return for that small bit of duplication is real control. The HTML side gets normal, debuggable CSS. And the PDF side gets normal, debuggable Typst functions. Neither one is fighting some abstraction layer like brand.yml that is built on top.
In the workshop, we build this from scratch on both sides. That way, you get to understand where every color and font decision lives.
Next email, I want to show you the other half of BIRD Investmentās fact sheet: the part where a table gets text to flow around it. Spoiler: This will need a Lua filter.
Best,
Albert
PS: If you havenāt grabbed a seat yet, registration for September 23 or September 25 is still open here:
Whenever youāre ready, there are three I can help you:
Automate Your Data Reports: This course helps data analysts eliminate manual copy-paste reporting by automating PDF reports end-to-end, saving hours every cycle and preventing costly mistakes. (Using the lovely Typst language š)
Generate Insights in Minutes, not Hours: This comprehensive course teaches you to handle data faster, smarter, and more efficiently.
Bespoke Data Science Solutions: Iāve helped clients build their own data science solutions. Whether building custom web apps, PDF reports, AI automations or teaching workshops, Iāve got you covered. You can reach out to me via this form (or simply hit reply to this email)

Reply