Insert a logo in upper right corner of R markdown html document

27,804

Solution 1

You can use htmltools::img with a little inline CSS for positioning. src can take a path directly, but when images aren't just handled like plots, sometimes knitting fails to convert images to a URI properly, which in turn causes them to fail to render. Using self_contained: false in the YAML is a quick solution, but it's not much harder to use knitr::image_uri to manually convert the image:

---
title: "Title"
author: "Author"
output: html_document
---


```{r, echo=FALSE}
htmltools::img(src = knitr::image_uri(file.path(R.home("doc"), "html", "logo.jpg")), 
               alt = 'logo', 
               style = 'position:absolute; top:0; right:0; padding:10px;')
```

---

# 1. Header

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor.

page with logo

Solution 2

The accepted answer works if you are using classical html output. If like me, you also work with bookdown, the logo need to appear on every pages. So, in case somebody find this answer but want to add a logo with bookdown, I give my proposition:

  • We need to create an external file with a script to be called in header, thankfully we can create it directly in the rmarkdown script.
  • We also use htmltools::img to allow including the image without external image file.

Here is my rmarkdown script to be used as an example:

---
title: "Logo with Bookdown"
author: "Author"
date: '`r format(Sys.time(), "%d %B, %Y")`'
output:
  bookdown::gitbook:
    includes:
      in_header: header.html
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

```{r htmlTemplate, echo=FALSE}
# Create the external file
img <- htmltools::img(src = knitr::image_uri(file.path(R.home("doc"), "html", "logo.jpg")), 
               alt = 'logo', 
               style = 'position:absolute; top:50px; right:1%; padding:10px;z-index:200;')

htmlhead <- paste0('
<script>
document.write(\'<div class="logos">',img,'</div>\')
</script>
')

readr::write_lines(htmlhead, path = "header.html")

```

# Page 1

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.

When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

```{r cars}
summary(cars)
```

# Page 2

You can also embed plots, for example:

```{r pressure, echo=FALSE}
plot(pressure)
```

Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.

Solution 3

I took a quite different approach to the answers above, using only CSS and without absolute positioning. I added the following CSS code chunk to my document, but you can also create a standalone CSS file and include that in the Rmd YAML header.

```{css, echo=FALSE}
#header {
  background-image: url("data: BASE64 encoded string for image");
  background-repeat: no-repeat;
  background-position: 95%;
  padding: 5px;
}
#header > * {
  max-width: calc(100% - 225px);
}
@media only screen and (max-width:600px){
#header > .title { 
  margin-top: 105px;
}
#header > *
  max-width: 100%;
}
#header {
  background-position: 10px 10px;
}
}
```

There's a few things going on here. To address the original question about the image, you need to base64 encode the image yourself and put the string into the background-image URL.

It also handles the issue of overlap of logo and header content in a reactive way, setting max-width on all header elements, and placing the logo above the title on narrow windows (less than 600px).

If you don't care about overlap at all, then you only really need the first #header selector code. If you don't care about the narrow device reactive layout then you can keep the first two selectors and drop the @media block.

The two pixel values 225px and 105px are based on my logo, and will need to be changed to fit your image plus some padding.

Solution 4

@alistaire's accepted answer was really useful. However in my case the title and the logo were overlapping, since the title in my markdown is really long.

Looking around I came up with the following solution, and I post it in case is useful for anybody.

```{js logo-js, echo=FALSE}
$(document).ready(function() {
  $('#header').parent().prepend('<div id=\"logo\"><img src=\"www/xxxxx.png\" style=\"position:absolute; top:0; right:0; padding:20px; height:120px\"></div>');
  $('#header').css('margin-right', '120px')
});
```

This should be added anywhere in the markdown, and of course it only works for HTML output. The idea is to add a new div for the logo, and then add a margin-right to the title so that it does not overlap.

Note that I don't think this is really optimal; my use of css is clumsy and if somebody figures out a better way I'm glad to hear. Anyhow it seems works ok.

Share:
27,804
Admin
Author by

Admin

Updated on October 22, 2021

Comments

  • Admin
    Admin over 2 years

    I'm trying to put my company logo on the right corner of my html document

    Here my code:

    <script>
      $(document).ready(function() {
        $head = $('#header');
        $head.prepend('<div class="knitr source"><img src="logo.png" width="220px" align="right"   ></div>')
      });
    </script>
    
    ---
    title: "Title"
    author: "Author"
    date: "Date"
    theme: bootstrap
    output: html_document
    keep_md: true
    ---
    
    ```{r echo=FALSE,  include=FALSE}
    knitr::include_graphics('./logo.png')
    ```
    
    <br>
    
    ## 1) Header
    
    <br>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo.
    

    However, because the logo.png is a local file when sharing the html document people are not able to see it.

    Additionally, I tried the following approach

    ---
    title: "Title"
    author: "Author"
    date: "Date"
    
    output: 
      html_document:
        css: markdown.css
        includes:
          in_header: extLogo.html
    ---
    

    where extLogo.html

    <div class="logos"><img src="logo.png" width="220px" align="right"></div>
    

    But it creates a div outside the div where the Title is (<div class="container-fluid main-container">). Can anyone help on this?

  • Admin
    Admin about 7 years
    how can I get always the logo right aligned with the title and the line below?
  • alistaire
    alistaire about 7 years
    What you're asking is vague: there are a lot of ways for it to be aligned in the same place under some conditions, but which would vary with screen size, scrolling, etc. I changed the above to position:absolute;, which seems more likely what you meant. If you mean within the title/author flexbox, that would take a JavaScript hack.
  • alistaire
    alistaire about 7 years
    You can still place the image relative to the bottom of the title div by indexing up from its natural location: library(htmltools); div(style = 'position:relative;', img(src = knitr::image_uri(file.path(R.home("doc"), "html", "logo.jpg")), alt = 'logo', style = 'position:absolute; top:-90px; right:0; padding:10px;') ) At some point it's a CSS question instead of an R one, though.
  • Nicolas Molano
    Nicolas Molano almost 4 years
    the logo as local file does not appears when shared the doc in other pc
  • lrnzcig
    lrnzcig almost 4 years
    you know you need to add a subdirectory called www in the code above, and put your logo there right?
  • Nicolas Molano
    Nicolas Molano almost 4 years
    the logo over laps with the title at some point (for example viewing it from a cell phone). @lrnzcig provides a good answer, however the issue of the local png file persist in that solution
  • Admin
    Admin over 3 years
    I've discovered that if you place the CSS in a standalone file and include it through the YAML, then local URLs for the image will be automatically base64 encoded for you. If you include the CSS as a code chunk (as I did in my example code) then Pandoc misses it and you must either manually encode the data URI (or use an external absolue URL to fetch the image from your institution's web servers)
  • Marco
    Marco over 3 years
    How can I control image size?
  • IsoBar
    IsoBar about 3 years
    @NicolasMolano's comment is true though, the logo disappears when the html is shared by its own without the folder holding the file. Is there a way to make it contained within the html like other figures embedded by knitr?
  • Nicolas Molano
    Nicolas Molano about 3 years
    @IsoBar The workaround for this was to store the image in a server and then pointing out to that url in the Rmardown document.
  • ethan tenison
    ethan tenison almost 3 years
    This is exactly what I want to do, but it won't read the image. So frustrating