Specifying CSS File Directory with xaringan
In this article, we will explore how to specify a CSS file directory using xaringan. We will delve into the issues that arise from using relative paths and discuss potential solutions.
Understanding Relative Paths in xaringan
When working with xaringan, you can use relative or absolute paths to link files. In the context of CSS files, the css parameter in the YAML header specifies the location of the CSS files.
Relative paths are useful when you want to reference a file from within the same directory. However, when using relative paths, it’s easy to get lost in navigating the directory structure. This is where problems arise.
In our example, we have multiple R Markdown/xaringan based slide decks with the same CSS files. Each lecture has an assets folder and things are working but the redundancy is driving us nuts. We want to use a file structure like this:
├── 01_introduction
│ └── lectures
│ ├── 01_Introduction.Rmd
│ ├── images
│ └── libs
├── 02_rmarkdown
│ └── lectures
│ ├── 02_RMarkdown.Rmd
│ ├── images
│ └── libs
├── assets
│ ├── cssninja-scaffold.css
│ ├── macros.js
│ ├── ninjutsu.css
│ └── sydney.css
└── slides_BST623_2023.Rproj
And our header YAML file looks like this:
---
title: "Introduction"
author: "me"
date: "`r format(Sys.time(), '%b %d, %Y')`"
output:
xaringan::moon_reader:
css: ["default", "assets/sydney.css", "assets/cssninja-scaffold.css", "assets/ninjutsu.css"]
lib_dir: libs
---
However, we need to use a file structure like this:
├── 01_introduction
│ └── lectures
│ ├── 01_Introduction.Rmd
│ ├── images
│ └── libs
├── 02_rmarkdown
│ └── lectures
│ ├── 02_RMarkdown.Rmd
│ ├── images
│ └── libs
└── slides_BST623_2023.Rproj
And our header YAML file should look like this:
---
title: "Introduction"
author: "me"
date: "`r format(Sys.time(), '%b %d, %Y')`"
output:
xaringan::moon_reader:
css: ["default", "../assets/sydney.css", "../../assets/cssninja-scaffold.css", "./assets/ninjutsu.css"]
lib_dir: libs
---
Specifying the Path with ../../
The first issue we face is how to specify a path like ../../ relative to the file’s directory.
When using ../../, it refers to the parent directory. So, in our example, if the CSS files are located in the assets folder of the project root, and we want to link them from within an R Markdown/xaringan based slide deck located at the same level as the assets folder, we can use ../../ like this:
---
title: "Introduction"
author: "me"
date: "`r format(Sys.time(), '%b %d, %Y')`"
output:
xaringan::moon_reader:
css: ["default", "../../assets/sydney.css", "../../assets/cssninja-scaffold.css", "../../assets/ninjutsu.css"]
lib_dir: libs
---
However, this approach has a problem. If the directory structure changes, and ../../ refers to an incorrect location, the links will break.
Specifying the Path with ./
The second issue we face is how to specify a path like ./assets relative to the project’s directory (instead of the file’s directory).
When using ./, it refers to the current working directory. So, in our example, if the CSS files are located in the assets folder of the project root, and we want to link them from within an R Markdown/xaringan based slide deck located at the same level as the assets folder, we can use ./ like this:
---
title: "Introduction"
author: "me"
date: "`r format(Sys.time(), '%b %d, %Y')`"
output:
xaringan::moon_reader:
css: ["default", "./assets/sydney.css", "./assets/cssninja-scaffold.css", "./assets/ninjutsu.css"]
lib_dir: libs
---
This approach also has a problem. If the directory structure changes, and ./ refers to an incorrect location, the links will break.
Using Absolute Paths with ../
Another approach is to use absolute paths instead of relative paths. We can achieve this by using the abspath() function from the utils package in R.
Here’s how we can specify an absolute path:
---
title: "Introduction"
author: "me"
date: "`r format(Sys.time(), '%b %d, %Y')`"
output:
xaringan::moon_reader:
css: ["default", abspath("assets/sydney.css"), abspath("assets/cssninja-scaffold.css"), abspath("assets/ninjutsu.css")]
lib_dir: libs
---
However, using absolute paths can be less flexible than using relative paths. If the directory structure changes, we need to update all the links.
Using Environment Variables
If we’re dealing with a large project with multiple R Markdown/xaringan based slide decks, it’s possible that the path of the CSS files may change over time.
In this case, using environment variables can be a good solution. We can define an environment variable for the path to the assets folder and use it in our code.
Here’s how we can specify the path with an environment variable:
---
title: "Introduction"
author: "me"
date: "`r format(Sys.time(), '%b %d, %Y')`"
output:
xaringan::moon_reader:
css: ["default", "${ASSETS_PATH}/sydney.css", "${ASSETS_PATH}/cssninja-scaffold.css", "${ASSETS_PATH}/ninjutsu.css"]
lib_dir: libs
---
And we can define the environment variable in our .Rprofile file:
# .Rprofile
# Define the path to the assets folder as an environment variable
setenv("ASSETS_PATH", "path/to/your/assets/folder")
By using environment variables, we can decouple the code from the specific directory structure and make it more flexible.
Conclusion
Specifying the paths to CSS files in R Markdown/xaringan based slide decks can be tricky. There are several approaches you can take depending on your project’s requirements.
Using relative paths with ../../ or ./ can work, but they have their own set of problems.
Using absolute paths can be a good solution, but it may not be the most flexible approach.
Using environment variables can provide a better level of flexibility and decouple the code from the specific directory structure.
Choose the approach that best suits your project’s requirements.
Last modified on 2023-10-04