Improve Quarto Documents by Including a Toggle for Code Folds

Author

Filip Reierson

Published

January 29, 2025

I often find that I want to include the code required to produce output in quarto documents. However, sometimes the code can make the quarto document messier to read through, especially for people who are not interested in the code. The code-fold option in quarto provides a way to make more space for content, while still making the code easily accessible. However, even the code fold buttons can take up unnecessary space. I have found an easy solution that uses OJS code chunks to create a toggle for the code folds. The trick is to modify the CSS conditioning on an input. In this article I use a checkbox.

Code
viewof show_code = Inputs.checkbox(['Show code folds']);

html`
<style>
.code-fold {
  display: ${show_code == 'Show code folds' ? 'block' : 'none'};
}
@media print {
  .hide-button {
    display: none;
  }
  .code-fold > summary {
    display: none;
  }
}
</style>
`
show_code = Array(0) []
Test out the checkbox

Additionally, I hide the checkbox and code fold buttons from the printed version of the webpage. To test this functionality press . Code that is expanded is still included in the printed version. I find that this approach provides the best balance between functionality and aesthetics.

Example

In a recent blog post I shared which is based on the “Anscombe’s quartet” dataset. To see how you can reproduce these results check the “Show code folds” option and then expand the code fold.

Code
library(tidyverse)
anscombe <- datasets::anscombe |>
  rowwise() |>
  mutate(
    'Dataset 1' = list(c('x' = x1, 'y' = y1)),
    'Dataset 2' = list(c('x' = x2, 'y' = y2)),
    'Dataset 3' = list(c('x' = x3, 'y' = y3)),
    'Dataset 4' = list(c('x' = x4, 'y' = y4))
  ) |>
  select(`Dataset 1`:`Dataset 4`) |>
  pivot_longer(everything()) |>
  unnest_wider(value)
anscombe |>
  group_by(name) |>
  summarise(mean_x = mean(x), 
            sd_x = sd(x),
            mean_y = mean(y),
            sd_y = sd(y),
            cor = cor(x,y),
            lm_intercept = coef(lm(y~x))[[1]],
            lm_slope = coef(lm(y~x))[[2]],
            lm_Rsq = summary(lm(y~x))$r.squared
            ) |>
  knitr::kable(digits = 3, col.names = c(
    c('', 'mean','sd','mean','sd','correlation','intercept','slope','R-squared')
  )) |>
  kableExtra::add_header_above(header = list(' ', 'x'=2,
                                          'y'=2, ' ', 'linear model'=3))
Table 1: Summary statistics for the “Anscombe’s quartet” dataset.
x
y
linear model
mean sd mean sd correlation intercept slope R-squared
Dataset 1 9 3.317 7.501 2.032 0.816 3.000 0.5 0.667
Dataset 2 9 3.317 7.501 2.032 0.816 3.001 0.5 0.666
Dataset 3 9 3.317 7.500 2.030 0.816 3.002 0.5 0.666
Dataset 4 9 3.317 7.501 2.031 0.817 3.002 0.5 0.667