head(penguins)
Quarto output styling
Overview
This extension (1) provides a Lua filter to add a CSS class to computational output that contains warnings, to distinguish between warnings and messages, and (2) provides CSS definitions for styling computational output, errors, warnings, and messages.
It lets you go from this:
…to this (using the default
setting):
…or this (using the minimal
setting):
You can also supply your own CSS rules and do whatever you want with the different types of output, using the custom
setting.
Installation
To install this extension in your current directory (or into the Quarto project that you’re currently working in), use the following terminal command:
quarto add andrewheiss/quarto-output-styling
This will install the extension in the _extensions
subdirectory. If you’re using version control, you will want to check in this directory.
Language support
The extension works with R, Python, Julia, and Observable JS computational output for HTML only. See these pages for more specific examples:
Usage
⭐✨⭐
See this page for full examples!
GitHub doesn’t allow for custom CSS, so nothing will be visible there.
⭐✨⭐
Enable the filter by including it in the YAML front matter of an HTML document:
---
title: Your title
filters:
- output-styling
---
By default, regular cell output will have a gray border and errors, warnings, and messages will be filled with different Bootstrap colors. You can change this by setting the appearance
option in the YAML front matter. There are three accepted values: default
, minimal
, and custom
.
default
The default option will include CSS styles that fill the output divs with different Bootstrap colors (see _extensions/output-styling/output-styling-default.css
for the complete CSS rules).
---
title: Your title
filters:
- output-styling
output-styling:
appearance: default # Filled text boxes
---
minimal
The minimal option will include CSS styles that only add colored borders to the output (see _extensions/output-styling/output-styling-minimal.css
for the complete CSS rules).
---
title: Your title
filters:
- output-styling
output-styling:
appearance: minimal # Unfilled text boxes with borders
---
custom
The custom option will not include any CSS. You’re responsible for doing that yourself. I’d recommend adapting from _extensions/output-styling/output-styling-default.css
or _extensions/output-styling/output-styling-minimal.css
.
Include the CSS however you want: in include-in-header
, in a separate CSS file, or as part of the theme with an SCSS file.
---
title: Your title
filters:
- output-styling
output-styling:
appearance: custom # Don't include any CSS
format:
html:
include-in-header:
- text: |
<style>
.cell-output.cell-output-stdout, /* Regular output for R and warnings for Julia */
.cell-output.cell-output-display, /* Regular output for Python and Julia and Observable JS */
.cell-output.cell-output-error, /* Errors for R and Python and Julia */
.cell-output.cell-output-stderr { /* Warnings and messages for R and Python */
margin: 0 0 1em;
padding: .4em;
border: 1px solid var(--bs-border-color);
border-radius: .25rem;
}
</style>---
Mixing styles
You can also use default
or minimal
and add your own custom CSS rules. Like here we can use minimal
and make warnings show up in Comic Sans (lol don’t actually do this):
---
title: Your title
filters:
- output-styling
output-styling:
appearance: minimal
format:
html:
include-in-header:
- text: |
<style>
.cell-output.cell-output-error {
font-family: "Comic Sans MS";
}
</style>---
Why this extension?
Not enough contrast between text and output in HTML
I don’t generally like how the HTML output for computational cells in R is styled by default—especially creating tutorials and lessons and other teaching materials. In the absence of stronger visual cues, I find that the output fades into the text too easily.
For example, here are the first few rows of the new-to-R-4.5 penguins
data:
species island bill_len bill_dep flipper_len body_mass sex year
1 Adelie Torgersen 39.1 18.7 181 3750 male 2007
2 Adelie Torgersen 39.5 17.4 186 3800 female 2007
3 Adelie Torgersen 40.3 18.0 195 3250 female 2007
4 Adelie Torgersen NA NA NA NA <NA> 2007
5 Adelie Torgersen 36.7 19.3 193 3450 female 2007
6 Adelie Torgersen 39.3 20.6 190 3650 male 2007
The only visual signal that this is computational output is the monospaced font.
This gets messier when using lots of chunks, like this:
1 + 1
[1] 2
and this:
mean(penguins$body_mass, na.rm = TRUE)
[1] 4201.754
Adding contrast with CSS
Fortunately it’s really straightforward to add custom styles to this output. Computational cells in Quarto follow a specific HTML template and get assigned specific CSS classes. Here’s the raw HTML output of 1 + 1
:
<div class="cell-output cell-output-stdout">
<pre>
<code>[1] 2</code>
</pre>
</div>
We can target that cell-output-stdout
class with CSS like this:
.cell-output.cell-output-stdout {
margin: 0 0 1em;
padding: .4em;
border: 1px solid var(--bs-border-color);
border-radius: .25rem;
}
.cell-output.cell-output-stdout pre {
margin-bottom: 0;
}
With that ↑ CSS, R code output cells have a small gray border now:
head(penguins)
species island bill_len bill_dep flipper_len body_mass sex year
1 Adelie Torgersen 39.1 18.7 181 3750 male 2007
2 Adelie Torgersen 39.5 17.4 186 3800 female 2007
3 Adelie Torgersen 40.3 18.0 195 3250 female 2007
4 Adelie Torgersen NA NA NA NA <NA> 2007
5 Adelie Torgersen 36.7 19.3 193 3450 female 2007
6 Adelie Torgersen 39.3 20.6 190 3650 male 2007
…and this:
1 + 1
[1] 2
…and this:
mean(penguins$body_mass, na.rm = TRUE)
[1] 4201.754
Distinguishing between errors, warnings, and messages
Quarto also emits a couple other specific CSS classes for computational output.
cell-output-stdout
: regular output<div class="cell-output cell-output-stdout"> <pre> <code>Regular output</code> </pre> </div>
cell-output-stderr
: messages and warnings<div class="cell-output cell-output-stderr"> <pre> <code>Message or warning</code> </pre> </div>
cell-output-error
: errors<div class="cell-output cell-output-error"> <pre> <code>An error</code> </pre> </div>
This means that messages/warnings and errors can also be targeted in specific ways:
.cell-output.cell-output-stdour {
/* Stuff for regular output */
}
.cell-output.cell-output-stderr {
/* Stuff for messages and warnings */
}
.cell-output.cell-output-error {
/* Stuff for errors */
}
Identifying warnings
However, there’s one downside! With R computational output, both warnings and messages use the cell-output-stderr
class, so there’s no way to style them differently.
To fix this, this extension uses a Lua filter to add a cell-output-warning
class to all computational cells that start with “Warning:”. They’re both still cell-output-stderr
, but warnings get an extra class.
Message:
<div class="cell-output cell-output-stderr"> <pre> <code>Message</code> </pre> </div>
Warning:
<div class="cell-output cell-output-stderr cell-output-warning"> <pre> <code>Warning</code> </pre> </div>
This allows you to adjust the styling for messages and warnings independently:
.cell-output.cell-output-stderr {
/* Stuff for messages */
}
.cell-output.cell-output-stderr.cell-output-warning {
/* Stuff for warnings only */
}
Do I even need to use this extension?
No! You can style most of the Quarto code output cells with regular old CSS.
The main reason this exists is for the Lua script to detect warnings and add the cell-output-warning
class to those divs. If you just want to have a border around cell output (or do any sort of styling), you can just add some CSS rules yourself.