Supporting your user’s preference for dark mode in an interactive, web-based R Markdown file is straightforward. The ability is not (yet) built in to most themes. I’ll show how to quickly add automatic dark mode to any theme in R Markdown.
If you want to skip straight to the finished product, check out dark-mode.Rmd
at https://github.com/thomasswilliams/r-markdown-snippets/blob/main/dark-mode.Rmd.
I scoured articles on dark mode in <insert choice of technology here>, looking for code that was a) current and b) simple. I went with CSS variables, which have great support in modern browsers, adapted from https://radek.io/posts/secret-darkmode-toggle/.
First, we need to create CSS variables for light (default) and dark colors:
/* specific colors for light and dark mode
adapted from https://radek.io/posts/secret-darkmode-toggle/ */
:root {
--background-color: #ffffff;
--font-color: #24272B;
/* can set other variables here as needed e.g. secondary font, secondary background etc. */
}
/* detect user preference colors
adapted from https://radek.io/posts/secret-darkmode-toggle/ */
@media (prefers-color-scheme: dark) {
:root {
--background-color: #24272B;
--font-color: #f6f6f6;
}
}
Adding (or referencing) this CSS in an R Markdown file will have no effect, as at this stage it’s merely defining variables. Next we need to use the variables to override colors:
/* override colors in R Markdown theme, with variables */
body {
/* colors from variables - need "!important" so takes priority over settings elsewhere */
background: var(--background-color) !important;
color: var(--font-color) !important;
}
/* headings */
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
color: var(--font-color) !important;
}
These few lines of CSS cover 80% of implementing automatic dark mode. The remaining 20% is identifying elements in the page that have explicit colors set by CSS, then overriding that with another color or variable. For example, here’s the CSS I came up with while including a DT data table and Highcharter chart (with some specific styles for just dark mode, leaving light mode as-is):
/* specific colors for light and dark mode
adapted from https://radek.io/posts/secret-darkmode-toggle/ */
:root {
--background-color: #ffffff;
--font-color: #24272B;
/* can set other variables here as needed e.g. secondary font, secondary background etc. */
}
/* detect user preference colors
adapted from https://radek.io/posts/secret-darkmode-toggle/ */
@media (prefers-color-scheme: dark) {
:root {
--background-color: #24272B;
--font-color: #f6f6f6;
}
/* any styles that should just apply to dark mode can be added here */
/* hacky dark mode code blocks */
pre {
filter: invert(0.8);
}
/* make striped rows less conspicuous
depending on version of data tables, may need one or more of the following selectors */
.table-striped > tbody > tr:nth-of-type(odd),
table.dataTable.stripe tbody tr.odd,
table.dataTable.display tbody tr.odd {
background-color: #f9f9f911;
}
/* hover rows less conspicuous */
.table-hover > tbody > tr:hover,
table.dataTable.hover tbody tr:hover,
table.dataTable.display tbody tr:hover {
background-color: #f5f5f522 !important;
}
}
/* override colors in R Markdown theme, with variables */
body {
/* colors from variables - need "!important" so takes priority over settings elsewhere */
background: var(--background-color) !important;
color: var(--font-color) !important;
}
/* headings */
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
color: var(--font-color) !important;
}
/* data tables div */
div.datatables {
color: var(--font-color) !important;
}
/* table rows */
table.dataTable tbody tr {
background-color: var(--background-color);
}
/* number of records */
.dataTables_info {
color: var(--font-color) !important;
}
The R Markdown file can be found at https://github.com/thomasswilliams/r-markdown-snippets/blob/main/dark-mode.Rmd.
Another option for dark mode in R Markdown is via a pre-made dark theme, such as downcute chaos
from https://juba.github.io/rmdformats/articles/examples/downcute_chaos.html.
Further reading: