1

Is it possible to use the CSS @font-face to provide font files to an RMarkdown?

e.g.:

<style>
@font-face {
    font-family: "Custom";
    src: url(https://github.com/stevecondylios/fonts/raw/master/CircularStd-Book.ttf) format("truetype");
}
body {
    font-family: "Custom", Verdana, Tahoma;
}
</style>

Note that the exact same css code above (less the style tags) does work when it's stored in an external .css file locally and referenced in the Rmd's yaml with

---
title: "My Rmarkdown doc"
date: "28 April 2020"
output: 
  html_document:
    css: mystyles.css
---

Ultimate goal

In case this is an A/B problem, my simple goal is to apply a custom font while avoiding using any local files beyond the Rmd file itself (i.e. no local external style sheets, although reading files from the web is fine).

I believe the only two options are either reading a font file in from the web within <style> ... </style>, or base64 encoding the font info within the tags of the Rmd itself. I've been trying both with little success.

A third option could be to provide a url (to a style sheet) to a yaml value, although I am not sure if that's possible

  html_document:
    code_folding: hide
    css: get_file(www.mysite.com/mystyles.css)

Further attempts

For good measure, I also tried

```{r}
css_url <- "https://github.com/stevecondylios/fonts/raw/master/CircularStd-Book.ttf"
```

<style>
@font-face {
    font-family: "Custom";
    src: url(`r css_url`) format("truetype");
}
body {
    font-family: "Custom", Verdana, Tahoma;
}
</style>
```

Update

I have learned you cannot declare @font-face in the HTML body, but must do so in the header. We can indeed add HTML tags into the RMarkdown header, but this reads in an external file, which is precisely what I'm trying to avoid, so am back to square 1.

stevec
  • 41,291
  • 27
  • 223
  • 311
  • 1
    Try to add ` – J_F Apr 30 '20 at 17:01
  • @J_F thanks for the suggestion. I tried, but there was no visible effect – stevec Apr 30 '20 at 17:05
  • 1
    Hm .. works fine for me, I see a difference. Did you use ` – J_F Apr 30 '20 at 17:13
  • 1
    @J_F ah, sorry, I know what that is, it's *trying* to apply the Circular font, failing, and instead applying the second preference (Verdana) (or possibly third preference, Tahoma). I guess the only way to detect whether it works is to recognise the circular font. Perhaps I should update with a more 'out there' font so it's extremely obvious once it works – stevec Apr 30 '20 at 17:16
  • @J_F after a lot of circling around dozens of similar questions and answers, I figured out a way to make it work. If you try it, (hopefully) you'll see the (subtle) difference in font. I suspect part of the reason this was difficult to solve is because there have been so many web standards over the years and therefore things that were or were not possible in the past get changed and SO answers become outdated. Thanks, in any case, for your help! – stevec May 01 '20 at 05:30

2 Answers2

1

For anyone else who wants to do this, this answer was what helped.

Basically:

  1. Download a .tff (font) file from any font website
  2. Convert it to base64 (on mac, simply base64 myfont.ttf > myfont_base64.txt
  3. Copy the contents of myfont_base64.txt in the placeholder below, and place the whole lot somewhere in your RMarkdown (it doesn't have to be in the HTML <head> as I previously suspected, but anywhere e.g. the <body> is fine)
<style>
@font-face {
    font-family: 'myfont';
    src: url(data:font/truetype;charset=utf-8;base64,<<copied base64 string>>) format('truetype');
    font-weight: normal;
    font-style: normal;
}
body { 
    font-family: "myfont", Verdana, Tahoma;
}
</style>
stevec
  • 41,291
  • 27
  • 223
  • 311
1

Starting with @stevec 's helpful answer, I was able to include a custom font within a single Rmarkdown file with no other files. Here is how this is achieved:

  1. Use base64encode() from the base64enc package to encode a font file.

    base64enc::base64encode("/path/fonts/ANYfont.ttf")
    #Output in R console is a very long string. Copy it.
    
  2. In the YAML section of your rmarkdown file, include a CSS YAML referencing the now base64 encoded font. (Usually the YAML CSS would have a file name as the value, but adding actual CSS as a string also works.)

     ---
     title: "Test"
     author: "seadata"
     output:
       html_document: 
       css: '@font-face {font-family: "myfont"; src: url(data:font/truetype;charset=utf-8;base64, 
    "YOUR_VERY_LONG_BASE_64_STRING GOES HERE" )
    format("truetype"); font-weight: normal; font-style: normal;
    }
    body { 
    font-family: "myfont";
    }'
     ---  
    
    

As you can see from the CSS, the example font was named "myfont" and is then referenced by that name to set the style for the HTML body tag with the font-family of "myfont".

SEAnalyst
  • 1,077
  • 8
  • 15