4.5 xaringan Presentation
- Get Start: https://slides.yihui.org/xaringan/#1
xaringanpackage- GitHub repo (refer to Wiki page for detailed documentation): https://github.com/yihui/xaringan
- remark.js
It is a slide template based on an HTML5 presentation framework remark.js.
Basically xaringan injected R Markdown (minus Pandoc) into remark.js. The slides are rendered by remark.js in the web browser, and the Markdown source needed by remark.js is generated from R Markdown (knitr).
You write slides in R Markdown, and then use the xaringan package to render the slides.
Features:
Interactive like html notes, but in form of slides, making it equivalent to PowerPoint, which students are more used to.
Support the choice of Google fonts.
Quote Xie, “The best fonts are always the fonts I have never used by myself.” I cannot agree more. 🤣
When you decide to use xaringan, read tutorials HERE.
To create a new xaringan presentation, you simply create a new R Markdown document and use the following YAML header:
---
title: "Presentation Ninja"
subtitle: "with xaringan"
author: "Yihui Xie"
date: "2016/12/12"
output:
xaringan::moon_reader:
css: ["xaringan-themer.css", "custom.css"]
lib_dir: libs
include:
in_header: libs/mathjax.html
nature:
highlightStyle: github
highlightLines: yes
countIncrementalSlides: false
ratio: '16:9'
---
One slide.
---
Another slide.xaringan::moon_reader is the main R Markdown output format in the xaringan package.
See the R help page ?xaringan::moon_reader for all possible configurations.
Configurations:
lib_dir: The directory to save the dependencies (e.g. jquery, bootstrap, etc.) of the slides.This is an argument passed to
rmarkdown::html_document. See the help page?rmarkdown::html_documentfor additional configurations provided byhtml_document.- By default this will be the name of the document with
_filesappended to it. - Here I set it to be
libs.
- By default this will be the name of the document with
includes: Named list of additional content to include within the document (typically created using theincludesfunction).in_header: Vector of file paths to be included in the document header (inside the<head>tag). Note that paths should be in quotation marks.before_body: Vector of file paths to be included immediately after the opening<body>tag.after_body: Vector of file paths h to be included immediately before the closing</body>tag.
Include multiple files by passing a vector of file paths.
includes: in_header: ["libs/mathjax.html", "libs/in_header.html"] after_body: ["theme/example-numbering.html", "libs/after_body.html"]Alternatively, use YAML list indentation with
-for each file:includes: in_header: - libs/mathjax.html - libs/in_header.html after_body: - theme/example-numbering.html - libs/after_body.htmlEach list item is treated as a separate file path.
nature: (Nature transformation) A list of configurations to be passed toremark.create(), e.g.list(ratio = '16:9', navigation = list(click = TRUE)).See Wiki page of
remark.jsfor all possible configurations.
4.5.1 Render Slides
There are two steps to render slides to pdf:
- Render
Rmdtohtmlwithrmarkdown::render - Print
htmltopdfwithpagedown::chrome_print
Two-in-one option:
✅ use renderthis package to render slides and print to pdf in one function.
This will call rmarkdown::render and then pagedown::chrome_print automatically. Will generate equity_valuation.html and equity_valuation.pdf accordingly based on your output formats.
Issue: Fonts are not embedded / applied in the pdf output.
Fix: Set pdf output font specifically.
@media print {
body {
font-family: 'Noto Sans', -apple-system, BlinkMacSystemFont, system-ui, Arial, sans-serif !important;
font-weight: 400 !important;
}
strong, b {
font-weight: 700 !important;
}
/* MathJax font for print */
.mjx-chtml {
font-family: 'Georgia Pro', 'Libertinus Serif', serif !important;
font-weight: 700 !important;
color: red !important; /* for testing purpose, whether selector is correct */
}
}Note that
.mjx-chtmlcontrols math typesetting. The tricky point is that MathJax CommonHTML math uses its own fonts for math rendering, and CSS font-family is NOT respected.Color and font-weight may work, but font-family is limited by MathJax’s internal font stack. For true font control, you need to change MathJax’s configuration, which is not easily done in xaringan.
html output and pdf output may use different fonts.
Issue: If keeping
@importin CSS, I cannot get the font applied in pdf output.Fix: What I do, a compromise solution, is to
- use system font for html output, and
- specify local font for pdf output.
4.5.2 Remark Markdown Basics
Remark.js uses its own flavor of Markdown, which is different from Pandoc’s Markdown! It is limited but should be sufficient for most use cases.
Features that are provided in Pandoc but missing in remark.js’s Markdown:
- fancy lists (ordered lists with letters, e.g., a., b., c., etc.)
4.5.2.1 Create a New Slide
Every new slide is created under three dashes (
---).Two dashes (
--) create a new fragment (incremental reveal) within the same slide.- Blank lines before and after the two and three dashes are required.
- No whitespace after the dashes.
The content of the slide can be arbitrary, e.g., it does not have to have a slide title, and if it does, the title can be of any level you prefer (
#,##, or###).
4.5.2.2 Slide Properties
A slide can have a few properties, including
classandbackground-image, etc.Properties are written in the beginning of a slide, e.g.,
The
classproperty assigns class names to the HTML tag of the slide, so that you can use CSS to style specific slides.This will apply class to the whole slide.
will be rendered as:
<div class="remark-slideshow"> <div class="remark-slide"> <div class="remark-slide-content center middle"> <h1>Slide with content centered in both dimensions</h1>Built-in classes include:
left,center,right,top,middleandbottom, which may be used to align entire slides.background-image: Sets a background image for the slide.name: Assigns a unique name to a slide, allowing for direct linking or referencing within the presentation (e.g.,slides.html#my-slide-name).
4.5.2.3 Add Attributes
Follow remark syntax to add attributes to elements.
Inline Attributes:
will be rendered as:
Nested inline attributes:
will be rendered as:
Block Attributes:
If you wish to have <div> tags instead, separate your content on new lines.
will be rendered as:
Another example:
will be rendered as:
<div class="footnote">
<span class="red bold">*</span>
Important footnote
</div>
<div class="footnote">
<div class="red bold">*</div>
Important footnote
</div>remark GitHub Wiki: Content Classes
4.5.3 Math Environments
Display math enclosed in double dollar signs ($$...$$), but note that
- the dollar signs (
$$) should not appear on separate lines - No space between
$$and the math content
In html tags, math should be enclosed in \( ... \) for inline math and \[ ... \] for display math.
- If using
$...$, there are backticks surrounding the math after rendering…
4.5.3.1 Color equations
In mathjax configuration file, define color macros, e.g., in
libs/mathjax.html:<!-- MathJax V2 Configuration --> <script type="text/x-mathjax-config"> MathJax.Hub.Config({ TeX: { extensions: ["color.js"], // load the color extension, support color names, RGB, and grey-scale color spaces equationNumbers: { autoNumber: "AMS" }, // use ams rules to number equations Macros: { // define colors red: ["{\\color[RGB]{185,64,71}{#1}}", 1], } } }); </script>In your slide, you can use the macros, e.g.,
\red{...},\blue{...}, etc.
4.5.4 Bullet list
Third level lists need an extra tab. ↩︎
Q: I think you need four spaces (or a true tab instead of two spaces) to indicate a new level. The syntax of remark.js’s Markdown is different with Pandoc’s Markdown. This works fine:
# Hello World
- Here are some bullet points using markdown syntax
- Here's the next level
- And this should be a lower level, but it isn't
- Whereas this is:
- To summarise:
- To get third level bullets:
- You have to use an extra tab on the third level.
1. No tabs
1. One tab
1. Two tabs
1. Three tabs4.5.4.1 Ordered list with letters
Issue: xaringan does not recognize letters as list markers for ordered lists by default.
Explain: xaringan uses remark.js to render slides, which uses its own markdown parser that does not support letters as list markers for ordered lists. You cannot “load” fancy_lists directly in xaringan even if you add pandoc_args: ["-f", "markdown+fancy_lists"] to your YAML. It won’t have an effect — because xaringan::moon_reader doesn’t use Pandoc’s list rendering and therefore will ignore the args. The Markdown is passed to remark.js, which uses its own internal syntax rules.
Fix: Use CSS to customize the list style or use html tags directly.
Define a custom class in CSS, e.g., in
custom.css:/* Lettered lists */ .remark-slide-content .alpha-list ol { list-style-type: lower-alpha; /* or upper-alpha for uppercase letters */ }Then you can apply this class to a list:
will be rendered as:
Use html tags directly:
<ol type="a"> <li>First item</li> <li>Second item <ol type="i"> <li>Subitem</li> <li>Subitem</li> </ol> </li> <li>Third item</li> </ol>will generate the same output as above.
4.5.5 Tables
Q: How to make the tables more compact, e.g, reduce the row height?
A: You can use CSS to adjust the table styles. For example, add the following CSS rules to your custom CSS file (e.g., custom.css):
/* Compact table styling */
.compact-table table {
line-height: 1.2;
font-size: 0.9em;
}
.compact-table th,
.compact-table td {
/* vertical padding: 2px; */
/* horizontal padding: 8px */
padding: 2px 8px !important;
}Then, in your slide, wrap your markdown table with a div that has the compact-table class:
.compact-table[
| Header 1 | Header 2 | Header 3 |
|----------|----------|----------|
| Row 1 | Data | More Data|
| Row 2 | Data | More Data|
]If your table is generated from R code, you can modify the HTML output to include the class:
```{r echo=FALSE, results='asis'}
tbl_html <- knitr::kable(df, format = "html") %>%
as.character()
tbl_html <- sub("<table", '<table class="compact-table"', tbl_html)
cat(tbl_html)
```Note that:
as.character()converts the HTML table to a character string so that you can manipulate it as text.sub("<table", '<table class="compact-table"', tbl_html)searches for the first occurrence of<tablein the HTML string; replaces it with<table class="compact-table". This adds the class.compact-tableto the<table>tag, which allows you to style it using your CSS (like the.compact-tableCSS you showed earlier).cat(tbl_html)prints the modified HTML string to the slide.catis required here because you want to output the HTML directly, not as a character string.
Q: I want to add more horizontal spacing in table cells, but keep narrow left spacing for the 1st column.
A: Add the following CSS rules to your custom CSS file (e.g., custom.css):
/* Add horizontal spacing in table cells, but keep narrow left spacing for the 1st column */
.fit-comp-table td,
.fit-comp-table th {
padding: 4px 18px !important; /* increase horizontal padding */
}
.fit-comp-table th:first-child,
.fit-comp-table td:first-child {
padding-left: 4px !important; /* tight left spacing for 1st column */
}Then, in your slide, wrap your table with a div that has the fit-comp-table class:
```{r echo=FALSE, results='asis'}
fit_comp <- tibble(
Metric = c("Residual Std. Error: CAPM", "Residual Std. Error: FF-3"),
AAPL = c("0.092", "0.089"),
SLAB = c("0.116", "0.107"),
KO = c("0.046", "0.044")
)
tbl_html <- fit_comp %>%
knitr::kable(format = "html", align = c("l", "c", "c", "c")) %>%
as.character()
tbl_html <- sub("<table", '<table class="fit-comp-table"', tbl_html)
cat(tbl_html)
```4.5.6 Images
Issue: Image resolution too low.
Fix: Add fig.retina=3 to chunk options for html output. Use dpi=300 for pdf output.
Issue: No figure numbering.
Explanation: xaringan uses remark.js to render slides, which does not support figure numbering. This is because referencing of figures across multiple slides is less common and potentially less effective for audience engagement. 😂
4.5.7 Presenter Notes
Q: Why using presenter notes?
A: A common mistake in presentations, especially for presenters without much experience, is to stuff a slide with too much content. The consequence is either a speaker, out of breath, reading the so many words out loud, or the audience starting to read the slides quietly by themselves without listening. Slides are not papers or books, so you should try to be brief in the visual content of slides but verbose in verbal narratives. If you have a lot to say about a slide, but cannot remember everything, you may consider using presenter notes.
Q: How to add presenter notes in xaringan?
A: In xaringan, presenter notes are written with ???.
Everything after ??? (on the same slide) will not appear on the slide, but will show up in presenter mode when you press p to toggle presenter view.
---
The holy passion of Friendship is of so sweet and steady
and loyal and enduring a nature that it will last through
a whole lifetime...
???
This is notes for presenter only.Q: What is the behavior of presenter mode?
A: The presenter mode shows thumbnails of the current slide and the next slide on the left, presenter notes on the right (see Section 7.3.5), and also a timer on the top right.
The keys c and p can be very useful when you present with your own computer connected to a second screen (such as a projector).
On the second screen, you can show the normal slides, while cloning the slides to your own computer screen and using the presenter mode.
Only you can see the presenter mode, which means only you can see presenter notes and the time, and preview the next slide. You may press t to restart the timer at any time.
⚠️ One thing to check: if you mirror your display instead of extending it, then the audience will see exactly what you see (including notes). To avoid this, make sure you use extended display mode so only you get the presenter view.
The figure below shows the Displays settings on macOS for extended display mode.
- Do not check the box “Mirror Displays”.
- Instead, separate the two displays, so you can drag the window with the normal view of slides to the second screen.

4.5.8 CSS and themes
The format xaringan::moon_reader has a css option, to which you can pass a vector of CSS file paths, e.g.,
The file path should contain the extension
.css. If a path does not contain a filename extension, it is assumed to be a built-in CSS file in thexaringanpackage.Make sure to insert the relative path to the file if it is not placed in the same directory as your
.Rmdfile.When you specify multiple CSS files, the one that comes later will take priority and override the previous ones if there are conflicting CSS rules.
To see all built-in CSS files, call
xaringan:::list_css()in R.When you only want to override a few CSS rules in the default theme, you do not have to copy the whole file
default.css; instead, create a new (and hopefully smaller) CSS file that only provides new CSS rules.Users have contributed a few themes to
xaringan. For example, you can use themetropolistheme (https://github.com/pat-s/xaringan-metropolis):
Read R Markdown: The Definitive Guide, Section 7.5 for more details about CSS and themes.
4.5.9 Smart Punctuation
xaringan-smartify provides a javascript hack to turn ugly quotes and dashes (' " -- ---) into their pretty versions (‘ ’ “ ” – —) in xaringan HTML slides.
Follow instructions on xaringan-smartify GitHub Repo.
4.5.10 Working offline
Making the slides work offline can be tricky, since you may have other dependencies. For example, if you used Google web fonts in slides (the default theme uses Yanone Kaffeesatz, Droid Serif, and Source Code Pro), they will not work offline unless you download or install them locally.
To make slides work offline, you need to download a copy of remark.js in advance, because xaringan uses the online version by default.
Refer to R Markdown: The Definitive Guide, Section 7.6.4 for details.
4.5.11 Parser
Remark default parser (default in xaringan):
Very lightweight, fast ✅
Recognizes special syntaxes like
.class[ text ],--for incremental reveals,???for presenter notesBut doesn’t support fenced divs
:::or Pandoc extensions like footnotes, definition lists, etc.
Pandoc parser (when you set
markdown: pandocin yaml):Full Pandoc Markdown support → you can use fenced divs, footnotes, definition lists, tables with alignment, math extensions, etc.
However, some remark-specific syntaxes may stop working or behave differently, especially:
.class[ text ]sometimes doesn’t parse as expectedIndentation rules for lists and code can be stricter
Incremental slides (
--) still work, but spacing quirks can appearRaw HTML might be handled slightly differently
4.5.12 xaringanExtra
The xaringanExtra package provides additional functionalities and themes for xaringan presentations.
Highlight features:
Add a search box to search through your slides with search
```{r xaringanExtra-search, echo=FALSE} # add search box xaringanExtra::use_search(show_icon = TRUE, position = "bottom-left") ```In your slides, press
Control+Fto start searching, or click on the search icon 🔍 if you setshow_icon = TRUE.Press
Enterto jump to the next match.On Mac,
- use
ctrl + Gto go to next match, andctrl + shift + Gto go to previous match. - use
escto exit search mode.
- use
Defaults to case-insensitive. Can be changed with
case_sensitive = TRUE.
Tile view
Tile view gives you a way to quickly jump between slides. Just press O (the letter O for Overview) at any point in your slideshow and the tile view appears.
Click on a slide to jump to the slide, or press O to exit tile view.
Add a progress bar at the bottom of your slides with progress bar
Might not be necessary if you page numbers already.
```{r xaringanExtra-progressbar, echo=FALSE}
# add progress bar
xaringanExtra::use_progress_bar(color="red", location="top", height="0.25em")
```