Custom CSS for HTML generated using RStudio

Update August 5 2014: I noticed this post is getting some hits; please note that it is an old post, it’s probably outdated and there’s likely to be a better solution by now

People have been telling me for a while that the latest version of RStudio, the IDE for R, is a great way to generate reports. I finally got around to trying it out and for once, the hype is justified. Start with this excellent tutorial from Jeremy Anglim.

Briefly: the process is not so different to Sweave, except that (1) instead of embedding R code in LaTeX, we embed R code in a document written using R Markdown; (2) instead of Sweave, we use the knitr package; (3) the focus is on generating HTML documents for publishing to the Web (see e.g. RPubs), although knitr can also generate PDF documents, just like Sweave.

It took me a little while to figure out a couple of things. First, how best to generate HTML tables, ideally using the xtable package. Second, how to override the default RStudio/R Markdown style. I’ve documented those tasks in this post.

I’m using RStudio version 0.96.330, installed on Ubuntu 12.04.

1. HTML tables using xtable
You can, of course, use R Markdown syntax to generate HTML tables. However, if like me you’re a fan of xtable, you can keep using it in R Markdown documents. This works because (1) xtable can generate HTML output and (2) where HTML syntax appears in a markdown document, it’s processed “as is” (i.e. ignored and output as HTML).

A simple example. In RStudio, open a new R Markdown document, enter the following code and save it with the extension .Rmd, e.g. tables.Rmd:


```{r table1, comment=NA, results='asis'}
print(xtable(head(iris, 10)), type = "html", include.rownames = F)

rstudio table1

A simple table using xtable + R Markdown

This outputs the first 10 rows of the iris dataset as a table. Things to note:

  1. Use comment=NA in the knitr chunk options to prevent lines of output beginning with ##
  2. Use results=’asis’ in the knitr chunk options so as the HTML is rendered, not printed
  3. Use type = “html” as an argument to print.xtable() for HTML tables

(update: comment=NA is redundant here; see the helpful comment from Yihui at end of post)

Hit the “Knit HTML” button in RStudio and you should see something like the image, right (click for larger version).

2. Custom CSS
Let’s say we want to alter the style of that table. First question: from where does RStudio get its default style? Answer: this CSS file which on my system, is found at /usr/lib/rstudio/resources/markdown.css. A glance at its contents shows, for example, why our HTML table has no border even though the HTML from xtable specifies “border=1”; table, td and th are all given the attribute border: none.

The document “Customizing Markdown Rendering” provides instructions to alter styles, but I found the structure of the document difficult to follow; it is not written in a step-by-step instructional style. Here’s what I did:

  1. Define your custom styles; I created a file named custom.css from the original markdown.css and saved it in the same directory as the R Markdown file, tables.Rmd with these modifications:
    table {
       max-width: 95%;
       border: 1px solid #ccc;
    th {
      background-color: #000000;
      color: #ffffff;
    td {
      background-color: #dcdcdc;
  2. Open a new R script file in RStudio and add the following content:
    options(rstudio.markdownToHTML = 
      function(inputFile, outputFile) {      
        markdownToHTML(inputFile, outputFile, stylesheet='custom.css')   

    Save it as e.g. style.R in the same directory as the markdown and CSS files. Note: you will need to specify the full path to the CSS file if it is not saved in the same directory.

  3. The important part: style.R has to be sourced in RStudio before the custom styles will be applied. With style.R as the active tab in RStudio, just click the “Source” button.

rstudio table2

The table with custom CSS applied

Finally, make tables.Rmd the active RStudio tab and click “Knit HTML” again. You should now see that the custom CSS has been applied to the document as shown on the right.

9 thoughts on “Custom CSS for HTML generated using RStudio

  1. One minor comment: comment=NA is redundant when results=’asis’, because ‘asis’ means knitr will do nothing to the output (no ## added either)

  2. Pingback: Custom CSS for HTML generated using RStudio | Estadística y R |

  3. If I do this, then Latex expressions don’t come out correctly anymore. So anything between $ $ is not correctly interpreted as Latex anymore? I have to restart R-Studio in order to have the knitr HTML button correctly recognize and interpret the latex expressions again?? This happens under Ubuntu and Windows, not sure whether it’s a problem with R-Studio or the markdown package.

      • If I use knit2html(myfile.rmd) from command line then an expression like $\frac{1}{x}$ does not come out right. If I simply press the KnitHTML button in R-Studio then $\frac{1}{x}$ comes out correctly as fraction.
        I think it has to do with the mathjax syntax change, see:
        If I use \frac{1}{x} then knit2html(myfile.rmd) works as does the R-Studio button.
        So the R-Studio button must do something more than simply call knit2html – because it does recognize the latex syntax, whereas knit2html() seems to follow the mathjax syntax. I guess I’ll use ... for inline math expressions from now on. Ugly, but seems to work. Cheers, J.

    • One solution is: don’t create the custom.css and style.R files. Just put your custom CSS at the top of the R Markdown file between the HTML tag style type=”text/css” … .

  4. Just want to point out that there are at least 2 other methods for generating nice-looking HTML tables from R, 1) gvisTable() in the GoogleVis package with examples at, and 2) Max Gordon’s htmlTable() documented on StackOverflow at
    Coming from Latex I’ve tried htmlTable() on complex table structures and so far the function behaves relatively well, similar to results you get from using latex() — so I recommend you give it a try.

Comments are closed.