92

In RMarkdown is there a way to specify the font color?

There doesn't seem to be an option while browsing through the chunk options

0

9 Answers 9

109

The answer given at the link provided by @Ben Bolker:

Roses are <span style="color:red">red</span>, 
violets are <span style="color:blue">blue</span>.

does work if you select HTML (ioslides) as the output format.

However, it does not work if you select pdf (beamer) as output format. If you want to create a pdf, use LaTeX syntax:

    Roses are \textcolor{red}{red}, violets are \textcolor{blue}{blue}.
5
  • 3
    Could you clarify the pdf part -- I cannot make it work: undefined control sequence \textcolor. The command is pandoc ./main.md -o ./main.pdf. The text in the main is the simplest \textcolor{red}{red}. What translation command do you use?
    – Ayrat
    Commented Aug 5, 2016 at 11:43
  • Dear Ayrat, I am using markdown within RStudio, so I am not very familiar with the pandoc commands. It is probably not related to the color command, but a problem with your system setup. See for example, here: stackoverflow.com/questions/37156696/… Commented Aug 8, 2016 at 7:20
  • 3
    If you're using R Markdown and a similar error appears, add header-includes: \usepackage{xcolor} in the preamble section
    – aldo_tapia
    Commented May 23, 2019 at 20:54
  • dr-harper.github.io/rmarkdown-cookbook/… here can you also find the full example about how to add color using LaTeX. Commented Aug 14, 2019 at 10:10
  • I suggest a minor improvement to this answer following @amanas' answer: change the text itself to be slightly different from just "red" or "blue", as in this example, it's not entirely clear what is the text color parameter red vs the actual word "red" that will be visible in-text.
    – spops
    Commented Dec 29, 2023 at 14:26
49

I create a function like this:

## Color Format
colFmt <- function(x,color) {
  
  outputFormat <- knitr::opts_knit$get("rmarkdown.pandoc.to")
  
  if(outputFormat == 'latex') {
    ret <- paste("\\textcolor{",color,"}{",x,"}",sep="")
  } else if(outputFormat == 'html') {
    ret <- paste("<font color='",color,"'>",x,"</font>",sep="")
  } else {
    ret <- x
  }

  return(ret)
}

Then you can use it inline like this:`r colFmt("MY RED TEXT",'red')`, and colored text will be rendered regardless of whether working on latex or HTML document.

5
  • Using an up-to-date Rstudio and rmarkdown::render for pdf output this gets converted to $\backslash$ in the tex file for me. Thus literally printing the string rather than interpreting it as latex. Very annoying. Do you have any ideas?
    – Midnighter
    Commented Dec 15, 2016 at 23:15
  • By any chance, is this happening in a table using xtable? Commented Dec 17, 2016 at 0:16
  • As you figured out, yes indeed, inside of xtable as per my answer.
    – Midnighter
    Commented Dec 18, 2016 at 21:43
  • Please, note that the HTML <font> tag is now obsolete. Its support could be removed at any time by browsers.
    – RLesur
    Commented Jun 8, 2019 at 17:48
  • @Nicholas Hamilton: Thank you for providing your very useful fct! How would I need to adapt it to work with transparent colors? See my SO question here
    – mavericks
    Commented Nov 5, 2020 at 9:41
29

This seems to work very well in both output formats, pdf and html:

Roses are $\color{red}{\text{beautiful red}}$, 
violets are $\color{blue}{\text{lovely blue}}$.

Hope it helps.

3
  • 1
    That worked for me for changing text color inline. Thanks for the suggestion. Just a note for others, that is LaTex syntax rather than R Commented Jun 25, 2018 at 20:52
  • 1
    This worked also for me! I want to point out that it is taking advance of LaTeX functionalities which maybe is not always possible. I imagine that it could cause font problems if you have a specific font for the text for example.
    – Garini
    Commented Oct 23, 2018 at 9:40
  • works well in Jupyter too, since it supports MathJax (subset of Tex and LaTex) jupyter-notebook.readthedocs.io/en/stable/examples/Notebook/…
    – prusswan
    Commented Nov 8, 2018 at 14:59
20

An output-format agnostic solution would be to use the dedicated text_spec() function in the kableExtra package:

Roses are `r kableExtra::text_spec("red", color = "red")`,

violets are `r kableExtra::text_spec("blue", color = "blue")`
10

Others have provided answers for output other than Word. For Word, you can use the Pandoc custom-style syntax to accomplish this with the aid of a reference word document. First, inside your reference.docx template, create a new Word style with a short, distinct name. If you want your font color to apply to a full paragraph, you can use the default, “Linked Paragraph and Character” style type. If you only want to emphasize some words in a paragraph with color, you need to select the “Character” style type. Change the font color (and any other styling you need) and save the reference.docx file.

Then, inside your .Rmd file, you can use the tag as follows:

<div custom-style=“DivCol”>Whole paragraph of colored text</div>

Just a <span custom-style=“SpanCol”>few words</span> of colored text

A word regarding style names - for reasons I don’t understand, this process did not work with the style name “Span_Add” but “SpanAdd” was fine.

3
  • I have read elsewhere that underscores can cause issues in chunk names etc, so I assume this is the reason. They recommend using a dash '-' rather than underscore '_' in these instances: github.com/rstudio/bookdown/issues/313, bookdown.org/yihui/rmarkdown/r-code.html
    – hugh-allan
    Commented Aug 5, 2021 at 5:54
  • Just confirmed that this solution also works with regular .md files. Pandoc converts it to .docx all the same without R's knittr.
    – Clokman
    Commented Aug 9, 2021 at 23:26
  • This does not seem to work for me. Do I need to do something in order to enable the use of the span tags?
    – Magnus
    Commented Aug 10, 2021 at 11:48
5

I basically used Nicholas Hamilton's answer but because I used xtable and print, I had some problems with certain latex sequences being escaped. Namely, \\textcolor being transformed to $\backslash$textcolor. I was able to get it right by avoiding sanitizing in the following way:

```{r results='asis'}
tbl = data.frame(a = letters[1:10], b = 1:10 / 10)
tbl$b = ifelse(tbl$b < 0.5, colFmt(tbl$b, "red"), colFmt(tbl$b, "green"))
print(xtable(tbl), sanitize.text.function = identity)
```

I then had to go and manually sanitize a few characters like % but at least \textcolor was correctly applied. Of course, this could be avoided by expanding your own sanitize function.

3
  • As I suspected. print(xtable(tbl), sanitize.text.function = identity) Commented Dec 17, 2016 at 3:07
  • sanitize.text.function = identity saves you having to create a trivial inline function Commented Apr 15, 2017 at 5:25
  • I thought your previous comment was sufficient but I've edited my answer to reflect the better practice.
    – Midnighter
    Commented Apr 16, 2017 at 19:45
2

For PDF and HTML, to get colored text which you can modify with markdown highlighting : see the rmarkdown book. Pandoc filter is the best choice.

For Microsoft word, you have to create first a Template_MS.docx with custom styles. Warning: create different styles for coloring paragraphs (paragraph style) and for colorings few words (character style). It is an option when you made a new style.

Add in th YAML:

---      
output:   
 word_document:   
    reference_docx: Template_MS.docx   
---   

And next:

For <span custom-style="Character1">few words</span> of colored text.

For paragraph.

<div custom-style="Paragraph1">Paragraph of colored text. Blabla. Blabla.</div>   

Nota Bene:
+ Do not use the same style for Paragraph and a few words, it is bugging.
+ If it is not working, check that your style is for paragraph ou character in MS.
+ If it is not working, install an updated version of pandoc.

1
  • This didn't work for me. Instead I had to add the following to my YAML (note the large gaps are because I cannot add newlines within a comment), which was based on this link: output: bookdown::word_document2: reference_docx: Template_MS.docx
    – LMc
    Commented Jan 7, 2021 at 18:52
2

Easily change the font color with sass

There's a new and better way of specifying colors or fonts in R Markdown:

  • Download the package sass
  • Create a chunk in your RMarkdown document with the following options {sass, echo = FALSE}
  • include the following SASS code in that chunk:
// This chunk contains SASS-code to specify font color

h1, h2, h3, h4, h5
  color: blue // Color for the headers

body
  color: red // Color for the text in the main part of your document

// The colors are only examples. You can change them to anything. You could also use hex codes.

You can also change much more than just the font color

Typically, I include something like this in my documents, to also change the font type, the sizes, the link colors etc.:

// These are variables, and are easy to change
$color: blue
$color2: red
$font: "Arial"
$font-size: 16px

h1, h2, h3, h4, h5
  color: $color
  font-family: $font
  font-weight: bold

body
  background-color: white
  color: black
  font-family: $font
  font-size: $font-size

a
  color: $color

a:link
  color: $color

a:hover
  background-color: $color2

You can change any HTML tag you can think of this way.

Read more about SASS here.

0

Use a lua filter when you render PDFs including beamer presentation and HTMLs including reveal.js

A lua filter enables you to specify the font colors in RMarkdown, Quarto Markdown (.qmd), and vanilla Pandoc Markdown in very easy and markdown-ish format. You just specify the font color by color names, e.g. [red]{color="red"}, or even by hexadecimal integers (hex), e.g. [red]{color="#FF6347"}.

Outputs

PDFs

enter image description here

beamer

enter image description here

HTMLs

enter image description here

reveal.js

enter image description here

MWEs

color-text.lua

Using a lua filter to change font colors is originally presented in 5.1 Font color | R Markdown Cookbook. This GitHub comment further elaborated the lua filter so that we can set font colors with hex codes.

The following lua filter is a modified version of the lua filter presented in the GitHub comment I mentioned above. The current version enables you to use the notations ([red]{color="red"} and [red]{color="#FF6347"}) when you render beamer and reveal.js presentation formats.

Span = function(span)
  color = span.attributes['color']
  -- if no color attribute, return unchange
  if color == nil then return span end

  -- tranform to <span style="color: red;"></span>
  if FORMAT:match 'html' or FORMAT:match 'revealjs' then -- Also available for revealjs
    -- remove color attributes
    span.attributes['color'] = nil
    -- use style attribute instead
    span.attributes['style'] = 'color: ' .. color .. ';'
    -- return full span element
    return span
  elseif FORMAT:match 'latex' or FORMAT:match 'beamer' then -- Also available for beamer
    -- remove color attributes
    span.attributes['color'] = nil
    -- encapsulate in latex code
    if string.sub(color, 1, 1) == "#" and #color == 7 then
      -- TODO: requires xcolor
      local R = tostring(tonumber(string.sub(color, 2, 3), 16))
      local G = tostring(tonumber(string.sub(color, 4, 5), 16))
      local B = tostring(tonumber(string.sub(color, 6, 7), 16))
      table.insert(
        span.content, 1,
        pandoc.RawInline('latex', '\\textcolor[RGB]{'..R..','..G..','..B..'}{')
      )
    elseif string.sub(color, 1, 1) == "#" and #color == 4 then
      -- TODO: requires xcolor
      local R = tostring(tonumber(string.sub(color, 2, 2), 16) * 0x11)
      local G = tostring(tonumber(string.sub(color, 3, 3), 16) * 0x11)
      local B = tostring(tonumber(string.sub(color, 4, 4), 16) * 0x11)
      table.insert(
        span.content, 1,
        pandoc.RawInline('latex', '\\textcolor[RGB]{'..R..','..G..','..B..'}{')
      )
    else
      table.insert(
        span.content, 1,
        pandoc.RawInline('latex', '\\textcolor{'..color..'}{')
      )
    end
    table.insert(
      span.content,
      pandoc.RawInline('latex', '}')
    )
    -- returns only span content
    return span.content
  else
    -- for other format return unchanged
    return span
  end
end

MWE

---
title: "Changing the font color"
output: 
  ## PDFs
  bookdown::pdf_document2:
    pandoc_args: 
      - "--lua-filter=color-text.lua"
  bookdown::beamer_presentation2:
    pandoc_args: 
      - "--lua-filter=color-text.lua"
  ## HTMLs
  bookdown::html_document2:
    # base_format: "function(..., number_sections) revealjs::revealjs_presentation(...)" # comment this line when creating ordinary HTMLs
    pandoc_args: 
      - "--lua-filter=color-text.lua"
    self_contained: false
always_allow_html: yes
link-citations: yes
---

## First

we define a Lua filter and write it to
the file `color-text.lua`.

```{cat, engine.opts = list(file = "color-text.lua")}
Span = function(span)
  color = span.attributes['color']
  -- if no color attribute, return unchange
  if color == nil then return span end

  -- tranform to <span style="color: red;"></span>
  if FORMAT:match 'html' or FORMAT:match 'revealjs' then -- Also available for revealjs
    -- remove color attributes
    span.attributes['color'] = nil
    -- use style attribute instead
    span.attributes['style'] = 'color: ' .. color .. ';'
    -- return full span element
    return span
  elseif FORMAT:match 'latex' or FORMAT:match 'beamer' then -- Also available for beamer
    -- remove color attributes
    span.attributes['color'] = nil
    -- encapsulate in latex code
    if string.sub(color, 1, 1) == "#" and #color == 7 then
      -- TODO: requires xcolor
      local R = tostring(tonumber(string.sub(color, 2, 3), 16))
      local G = tostring(tonumber(string.sub(color, 4, 5), 16))
      local B = tostring(tonumber(string.sub(color, 6, 7), 16))
      table.insert(
        span.content, 1,
        pandoc.RawInline('latex', '\\textcolor[RGB]{'..R..','..G..','..B..'}{')
      )
    elseif string.sub(color, 1, 1) == "#" and #color == 4 then
      -- TODO: requires xcolor
      local R = tostring(tonumber(string.sub(color, 2, 2), 16) * 0x11)
      local G = tostring(tonumber(string.sub(color, 3, 3), 16) * 0x11)
      local B = tostring(tonumber(string.sub(color, 4, 4), 16) * 0x11)
      table.insert(
        span.content, 1,
        pandoc.RawInline('latex', '\\textcolor[RGB]{'..R..','..G..','..B..'}{')
      )
    else
      table.insert(
        span.content, 1,
        pandoc.RawInline('latex', '\\textcolor{'..color..'}{')
      )
    end
    table.insert(
      span.content,
      pandoc.RawInline('latex', '}')
    )
    -- returns only span content
    return span.content
  else
    -- for other format return unchanged
    return span
  end
end
```

Now we can test the filter with some text in brackets with
the `color` attribute, e.g.,

> Roses are [red and **bold**]{color="red"} and
> violets are [blue]{color="blue"}.

> Roses are [red and **bold**]{color="#FF6347"} and
> violets are [blue]{color="#6a5acd"}.

Not the answer you're looking for? Browse other questions tagged or ask your own question.