How to Make R Markdown Snow

Much like ice sculpting, applying powertools to absolutely frivolous pursuits

Emily Riederer


December 11, 2021

Last year, I tweeted about how to spread holiday cheer by letting your R Markdown documents snow. After all, what better to put people in the holiday spirit than to add a random 5% probability that whatever part of a document they are trying to read will be covered?

I make no promises that this will amuse your recipients, but at least it seemed to strike a cord with other R Markdown creators. This year, I decided to write it up step-by-step. As silly as the example is, I think it demonstrates (through slight abuse) some useful features of R Markdown. Much like ice sculpting, we will apply the powertool that is R Markdown to achieve our rather fanciful end.

If you want to skip the discussed, you can check out the full project, the main R Markdown file, or the rendered output. The rendered output is also shown below:

In the rest of this post, I’ll touch on three R Markdown tricks and their fanciful uses:

We will see how to dress up this very important business R Markdown

Much more useful applications of these same features are discussed in the linked sections of the R Markdown Cookbook.

Child documents

Child documents allow R Markdown authors to combine multiple R Markdown files into a single final output rendered in a consistent environment. This helps create a more manageable, modular workflow if you are working on a long project or anaylsis with many distinct parts or if there are some pieces of boilerplate text or analysis that you wish to inject into many projects.

To add child documents, we create an empty R code chunk, and use the child chunk option to pass the path to the R Markdown file that we wish to include. In our case, we reference our snow.Rmd file.

```{r child = "snow.Rmd"}`r ''`

Of course, since child documents are functionally the same as including files in the same document, we could have included this material in the same file. However, since snowflakes should clearly only be placed in very important documents, it is good to use best practices and take a modular approach. Tactically, this also makes it easier to “turn them on an off” at will or swap them our for New Years fireworks, Valentine’s Day hearts, and more.

Including HTML and CSS

So, what is in the snow.Rmd file?

First, we have to bring in the snowflakes themselves.

<div class="snowflakes" aria-hidden="true">
  <div class="snowflake">
  <!-- many more snowflakes... -->

Because this R Markdown will render to an HTML document, we are free to include raw HTML text the same way we include narrative, English-language text. Here, I wrap unicode snowflakes in <divs> so I can attach CSS classes to them.

Similarly, R Markdowns that will be rendered to HTML can use all the benefits of web technology like CSS and JavaScript. Custom CSS can be included either with the css language engine or a reference in the YAML header to an external .css file. For compactness, I go with the former.

A css chunk adds CSS code used to animate the snowflake divs. This is taken nearly verbatim from this CodePen. Since this is rather lengthy, we can also use the echo = FALSE chunk option to not output all of the CSS in our final document.

```{css echo = FALSE}`r ''`
<<css goes here>>

For more tips on writing CSS for R Markown, check out my post on finding the right selectors.

Conditional chunk evaluation

The above two tricks are as for as my demo goes since I only planned to render it once. However, if you are creating automated reports and fear your recipients have limited patience for animated snowflakes, we can also use R Markdown chunk options with variables as arguments to only allow these snowflakes to appear during a certain time period.

So, for example instead of:

```{r child = "snow.Rmd"}`r ''`

We might type:

```{r child = "snow.Rmd", eval = (substr(Sys.Date(), 6, 7) == 12)}`r ''`

To only allow the child document to be included in December.

If we had chosen not to use child documents, we could also use chunks to achieve conditional evaluation using the asis engine.