---
title: "tableHTML"
author: "Theo Boutaris"
date: "`r Sys.Date()`"
output: 
  html_document
vignette: >
  %\VignetteIndexEntry{tableHTML tutorial and shiny}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

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

This is a package for building CSS-ible HTML tables in an easy and intuitive way. These are compatible
with any application that accepts HTML (e.g. shiny, rmarkdown, Outlook, PowerPoint, Word). 
The main function `tableHTML` will convert a data.frame or matrix or any other object that can be
converted into a data.frame into an HTML table. Using the function on R Studio will print the table
on the viewer otherwise it will use the default browser. The default tables are built without any 
CSS in order to allow for full flexibility in design.

In order to see the most basic example with tableHTML you could type:

```{r basic}
library(tableHTML)
tableHTML(mtcars)
```

### Removing Row Names

To remove row names from the HTML table you can type:

```{r rownames}
tableHTML(mtcars, rownames=FALSE)
```

### Adding a table class

The class argument sets the class name for the table. The default will be of the form 
table\_xxx (random 4-digit number). This makes it easier to add css to it in case there 
are multiple tables.

```{r, eval=FALSE}
mytable <- tableHTML(mtcars)
str(mytable)
# Classes 'tableHTML', 'html', 'character'  atomic [1:1] 
# <table class=table_1901 border=1 style="border-collapse: collapse;">
# <tr>
#   <th id="tableHTML_header_1"> </th>
#   <th id="tableHTML_header_2">mpg</th>
#   <th id="tableHTML_header_3">cyl</th>
# truncated...
```

And with a custom class:

```{r, eval=FALSE}
mytable <- tableHTML(mtcars, class='myClass')
str(mytable)
# Classes 'tableHTML', 'html', 'character'  atomic [1:1] 
# <table class=myClass border=1 style="border-collapse: collapse;">
# <tr>
#   <th id="tableHTML_header_1"> </th>
#   <th id="tableHTML_header_2">mpg</th>
#   <th id="tableHTML_header_3">cyl</th>
# truncated...
```


### Adding Second Headers that span multiple columns

In case you would like to add second headers that span multiple columns you can do it by providing a
list in the `second_header` argument. The first element will contain the column spans 
(i.e. a numeric atomic vector) whereas the second element will contain the names 
(i.e. a character atomic vector).

For example:

```{r secondheader}
tableHTML(mtcars, second_headers = list(c(3, 4, 5), c('col1', 'col2', 'col3')))
```

### Adding Row Groups that span multiple rows

In case you would like to add row groups that span multiple rows you can do it by providing a
list in the `row_groups` argument. The first element will contain the row spans 
(i.e. a numeric atomic vector) whereas the second element will contain the names 
(i.e. a character atomic vector).

For example:

```{r rowgroups}
tableHTML(mtcars, 
          rownames = FALSE, 
          row_groups = list(c(10, 10, 12), c('Group 1', 'Group 2', 'Group 3')))
```

### Change the widths

Obviously, the above tables are far from appealing since they have no css. So we can start styling
them now. A very important feature is to be able to control the column widths. You can do this with
the widths argument. 

The widths argument specifies the columns' width in pixels. It needs to have the same length as the
number of columns (if rownames is TRUE, rownames are also considered a column). 
If second headers exist these will stretch according to their underlying columns' widths. 

As an example:

```{r widths}
tableHTML(mtcars, 
          widths = rep(100, 12), 
          second_headers = list(c(3, 4, 5), c('col1', 'col2', 'col3')))
```

### Change the border

By default the table border is set to 1. If you set to 0 it will remove all the lines (the grid) 
completely. Setting it to an integer greater than 1 will increase the size of the table's outside
border.

```{r border}
tableHTML(mtcars, border = 0)
```

### Adding a caption

If you want a caption (title) for your table you can add one with the caption argument.

```{r caption}
tableHTML(mtcars, caption = 'This is  a table')
```


### Adding a footer

If you want a footer for your table you can add one with the footer argument.

```{r footer}
tableHTML(mtcars, footer = 'This is  a footer')
```

### Collapse the table

By default tableHTML collapses the table, so that there is no spacing between cells. You can change
this behaviour by using the collapse argument.

```{r collapse, eval=FALSE}
tableHTML(mtcars, collapse = 'separate')
```

![  ](collapsed.PNG)

\     

In order to use a non-collapsed table on shiny you need to use the `collapse = 'separate_shiny'`
argument. shiny uses bootstrap 3 by default which uses 
`table {border-collapse: collapse; border-spacing:0;}` in its css. `collapse = 'separate_shiny'`
will use the `!important` keyword in HTML which overwrites the default bootstrap 3 styling. Web
developers argue that using `!important` can be dangerous since it overwrites previously set styles,
so only use it on shiny or other web applications where tables are collapsed by default.

```{r collapse2}
tableHTML(mtcars, collapse = 'separate_shiny')
```

### Spacing

If collapse is either separate or separate_shiny then you can use the spacing argument to change
the spacing between the cells. This only works if collapse is separate or separate_shiny otherwise
it is not taken into account. You can use one or two length distances. If two length distances are
used, the first specifies the horizontal spacing and the second one the vertical spacing.

```{r spacing1}
tableHTML(mtcars, collapse = 'separate_shiny', spacing = '2px')
```

\     

```{r spacing2}
tableHTML(mtcars, collapse = 'separate_shiny', spacing = '5px 2px')
```

### Escaping

By default `tableHTML` will escape `<` and `>` because they open or close the table's tags if 
they are part of the text of the data.frame, which results into missing text. For example you 
can see the difference below:

```{r escaping} 
df <- data.frame(a = c('abcd<efgh'))
tableHTML(df, escape = FALSE, rownames = FALSE)
```

\

```{r escaping_2}
tableHTML(df, escape = TRUE, rownames = FALSE)
```

\

In order to fix this, the argument `escape` is set to `TRUE` by default. `<` and `>` will be replaced
with `&#62` and `&#60`. However, if you would like to include clickable links in your HTML table you 
should **not** escape by setting `escape = FALSE`.

------

## add\_css\_* family

These functions add inline CSS to the HTML table. The package has been developed so that the 
functions are chained with the `%>%` (pipe) operator which comes from the `magrittr` package. 
You can chain as many of those as you want
when building your HTML table. The CSS code is added within the HTML table. This is ok for simple
table styling but for more complex CSS styles (like the hover selector) it would still require a
separate css file (we will see how to work with those in shiny later on).

### add\_css\_row

In order to add css to specific table rows you need to use the `add_css_row` function. The function
has three arguments:

1. *tableHTML*: A tableHTML object (created by `tableHTML()`)
2. *css*: A list of two elements with the corresponding css. The first element of the list should 
          be an atomic vector with the style definitions (e.g. background-color). The second element
          will be an atomic vector with the same length as the first element, which will contain the
          style definitions' values (e.g. red).
3. *rows*: A numeric atomic vector with the indices of the rows on which the style definitions 
           will be applied. **headers and second_headers are also part of the rows**. Default is NULL
           which means that it will be applied to all rows.

For example:

```{r addcssrow1}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11))) %>% 
  add_css_row(css = list(c('background-color', 'border'), c('lightblue', '2px solid lightgray')))
```

\    

And adding row indices manually:

```{r addcssrow2}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11))) %>% 
  add_css_row(css = list(c('background-color', 'border'), c('lightblue', '2px solid lightgray')),
              rows = 2:33)
```

\   

It is very common in HTML tables to highlight odd rows with one color and even rows with another.
We can achieve this with the rows argument and the helper funtions from the tableHTML package `odd`
and `even`.

```{r addcssrow3}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11))) %>% 
  add_css_row(css = list('background-color', '#f2f2f2'),
              rows = odd(1:33)) %>%
  add_css_row(css = list('background-color', '#e6f0ff'),
              rows = even(1:33))
```

### add\_css\_column

In order to add css to specific table columns you need to use the `add_css_column` function.
The function will add css to the columns, but not to the headers and second_headers. To add css
to those you would need to use `add_css_header` and `add_css_second_header` respectively. In HTML
terminology `add_css_row` modifies the _td_ tag.
The function has three arguments:

1. *tableHTML*: A tableHTML object (created by `tableHTML()`)
2. *css*: A list of two elements with the corresponding css. The first element of the list should 
          be an atomic vector with the style definitions (e.g. background-color). The second element
          will be an atomic vector with the same length as the first element, which will contain the
          style definitions' values (e.g. red).
3. *columns*: A character/numeric atomic vector with the names/indices of the columns where the style
              definitions will be applied on. At least one column name/index must be provided. 
              If the rownames are included the column name is implied to be "rownames" and the 
              index 0. If row groups are included the column name is implied to be "row_groups" 
              and the index -1.

For example:

```{r add css column 1}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11))) %>% 
  add_css_column(css = list(c('background-color', 'border'), c('lightblue', '3px solid lightgray')), 
                 columns = c('cyl', 'hp', 'rownames'))
```

\    

Keep in mind that if you apply the **same** style to both rows and columns, column styles will 
overwrite row styles:

```{r addcsscolumn2}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11))) %>% 
  add_css_row(css = list('background-color', '#f2f2f2')) %>%
  add_css_column(css = list('background-color', 'lightblue'), 
                 columns = c('cyl', 'hp', 'rownames')) 
 
```

In general inner tag style definitions will overwrite outer tag style definitions.    

For example:

```{r, eval=FALSE}
mytable <- tableHTML(mtcars)
print(mytable, viewer = FALSE)
<table style="border-collapse:collapse;" class=table_2079 border=1>
<thead>
<tr>
  <th id="tableHTML_header_1"> </th>
  <th id="tableHTML_header_2">mpg</th>
  <th id="tableHTML_header_3">cyl</th>
truncated...
```

`add_css_row` will add the style definitions in `<tr>` whereas `add_css_header` will add the css
in `<th>`. Since the `<th>` tag is within the `<tr>` tag, the style definitions of `th` will 
overwrite those of `tr`. This is only true for the **same** style definitions i.e. if you specify
a `background-color` for both the first row and the headers.

### add\_css\_rows\_in\_column

This function is used to add different css values of the same css definition across the 
column of the table. For example if you want to specify different colours for each one of
the rows of a column, this is the right function.

The function accepts only one column but as usual you can chain multiple
`add_css_rows_in_column`s.

```{r addcssrowsincolumn}
 tableHTML(mtcars) %>%
   add_css_rows_in_column(css = list('background-color', 
                                    rep(c('red', 'green'), each = 16)),
                         column = 'mpg')
```

\

Here we chain two columns together

```{r addcssrowsincolumn2}
 tableHTML(mtcars) %>%
   add_css_rows_in_column(css = list('background-color', 
                                    rep(c('red', 'green'), each = 16)),
                         column = 'mpg') %>%
   add_css_rows_in_column(css = list('background-color', 
                                    rep(c('green', 'red'), each = 16)),
                         column = 'cyl')
  

```

\

This can be chained with `add_css_column` or any of the rest of the `add_css*` functions
as seen previously.

```{r addcssrowsincolumn3}
 tableHTML(mtcars) %>%
   add_css_column(css = list('border', '3px solid blue'),
                  columns = c('mpg', 'disp', 'rownames')) %>%
   add_css_rows_in_column(css = list(c('background-color'), 
                                    rep(c('red', 'green'), each = 16)),
                         column = 'mpg')
  
     
```


### add\_editable\_column

This function is used to create editable columns. This is done in HTML so the underlying 
data in your data.frame will not change. This is meant to be used with shiny or JavaScript in your
application / dashboard / website.

```{r editablecol}
 tableHTML(mtcars) %>%
   add_editable_column(columns = 'mpg')
```

### add\_css\_header

In order to add css to specific table headers you need to use the `add_css_header` function. 
The function has three arguments:

1. *tableHTML*: A tableHTML object (created by `tableHTML()`)
2. *css*: A list of two elements with the corresponding css. The first element of the list should 
          be an atomic vector with the style definitions (e.g. background-color). The second element
          will be an atomic vector with the same length as the first element, which will contain the
          style definitions' values (e.g. red).
3. *headers*: A numeric atomic vector with the indices of the headers where the style definitions 
              will be applied on. At least one header index must be provided.

For example:

```{r addcssheader1}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11))) %>% 
  add_css_header(css = list('background-color', 'lightgray'), headers = c(1, 4))
```

### add\_css\_second\_header

In order to add css to specific table second headers you need to use the 
`add_css_second_header` function. The function has three arguments:

1. *tableHTML*: A tableHTML object (created by `tableHTML()`)
2. *css*: A list of two elements with the corresponding css. The first element of the list should 
          be an atomic vector with the style definitions (e.g. background-color). The second element
          will be an atomic vector with the same length as the first element, which will contain the
          style definitions' values (e.g. red).
3. *second_headers*: A numeric atomic vector with the indices of the second headers where the 
                     style definitions will be applied on. At least one second header index must 
                     be provided.
For example:

```{r addcsssecondheader1}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11)), 
            second_headers = list(c(3, 4, 5), c('col1', 'col2', 'col3'))) %>% 
  add_css_second_header(css = list(c('background-color', 'border'), 
                                   c('lightgray', '3px solid green')),
                        second_headers = c(1, 3))  
```

### add\_css\_caption

In order to add css to the caption you need to use the 
`add_css_caption` function. The function has two arguments:

1. *tableHTML*: A tableHTML object (created by `tableHTML()`)
2. *css*: A list of two elements with the corresponding css. The first element of the list should 
          be an atomic vector with the style definitions (e.g. background-color). The second element
          will be an atomic vector with the same length as the first element, which will contain the
          style definitions' values (e.g. red).

```{r addcsscaption}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11)), 
            caption = 'This is a table') %>% 
  add_css_caption(css = list(c('color', 'font-size', 'text-align'), c('blue', '20px', 'left')))  
```

### add\_css\_footer

In order to add css to the caption you need to use the 
`add_css_caption` function. The function has two arguments:

1. *tableHTML*: A tableHTML object (created by `tableHTML()`)
2. *css*: A list of two elements with the corresponding css. The first element of the list should 
          be an atomic vector with the style definitions (e.g. background-color). The second element
          will be an atomic vector with the same length as the first element, which will contain the
          style definitions' values (e.g. red).

```{r addcssfooter}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11)), 
            footer = 'This is a footer') %>% 
  add_css_footer(css = list(c('color', 'font-size', 'text-align'), c('blue', '20px', 'left')))  
```

### add\_css\_thead

In order to add css to both the headers and second headers (if any) you could use the 
`add_css_thead` function. The function has two arguments:

1. *tableHTML*: A tableHTML object (created by `tableHTML()`)
2. *css*: A list of two elements with the corresponding css. The first element of the list should 
          be an atomic vector with the style definitions (e.g. background-color). The second element
          will be an atomic vector with the same length as the first element, which will contain the
          style definitions' values (e.g. red).

```{r addcssthead}
mtcars %>%
  tableHTML() %>% 
  add_css_thead(css = list('background-color', 'lightgray')) 
```

### add\_css\_tbody

In order to add css to all the table apart from the headers or second headers you could use the 
`add_css_tbody` function. The function has two arguments:

1. *tableHTML*: A tableHTML object (created by `tableHTML()`)
2. *css*: A list of two elements with the corresponding css. The first element of the list should 
          be an atomic vector with the style definitions (e.g. background-color). The second element
          will be an atomic vector with the same length as the first element, which will contain the
          style definitions' values (e.g. red).

```{r addcsstbody}
mtcars %>%
  tableHTML() %>% 
  add_css_tbody(css = list('background-color', 'lightgray')) 
```

\    

**Note**: As mentioned above inner tag styling overwrites the same outer tag styling. In this case
`tr` (add\_css\_row), and `td` (add\_css\_column) styling will overwrite the same styling specified
in `thead` or `tbody`.

To demonstrate this with an example:

```{r theadexample1}
mtcars %>%
  tableHTML() %>% 
  add_css_thead(css = list('background-color', 'lightgray')) %>%
  add_css_row(css = list('background-color', 'blue'), rows = 1)
```

\    

```{r theadexample2}
mtcars %>%
  tableHTML() %>% 
  add_css_tbody(css = list('background-color', 'lightgray')) %>%
  add_css_row(css = list('background-color', 'blue'), rows = c(4, 6))
```

### add\_css\_table

In order to add css to the whole table you need to use the 
`add_css_table` function. The function has two arguments:

1. *tableHTML*: A tableHTML object (created by `tableHTML()`)
2. *css*: A list of two elements with the corresponding css. The first element of the list should 
          be an atomic vector with the style definitions (e.g. background-color). The second element
          will be an atomic vector with the same length as the first element, which will contain the
          style definitions' values (e.g. red).

```{r addcsstable}
mtcars %>%
  tableHTML() %>% 
  add_css_table(css = list('background-color', 'lightgray')) 
```

\      

`<table>` is the outest tag in an HTML table which means that any **same** style definitions in any
other tags will overwrite the table tag's style definitions in the same way as described in the
above cases.

### All together

An example to put everything in action:

```{r alltogether}
mtcars %>%
  tableHTML(widths = c(140, rep(45, 11)),
            second_headers = list(c(3, 4, 5), c('team1', 'team2', 'team3')),
            caption = 'Table of Cars',
            footer = 'Figure 1. Stats for famous cars') %>% 
  add_css_second_header(css = list(c('height', 'background-color', 'font-size'), 
                                   c('40px', ' #e6e6e6', '30px')),
                        second_headers = 1:3) %>%
  add_css_header(css = list(c('height', 'background-color'), c('30px', ' #e6e6e6')),
                 headers = 1:12) %>%
  add_css_row(css = list('background-color', '#f2f2f2'),
              rows = even(1:34)) %>%
  add_css_row(css = list('background-color', '#e6f0ff'),
              rows = odd(1:34)) %>%
  add_css_column(css = list('text-align', 'center'), 
                 columns = names(mtcars)) %>%
  add_css_caption(css = list(c('text-align', 'font-size', 'color'), c('center', '20px', 'black'))) %>%
  add_css_footer(css = list(c('text-align', 'color'), c('left', 'black')))
```

### make_hyperlink

This function is used to create clickable links in your table. Under the hood
it adds the `a href` tag to your data in order to be displayed as a link. In order
for the links to display properly, the `escape` argument needs to be set to `FALSE`.

The second argument in `make_hyperlink` can give an alias to the links.

```{r hyperlink1}
#escape needs to be set to FALSE
tableHTML(data.frame(cran = make_hyperlink(c('https://cran.r-project.org/',
                                             'https://cran.r-project.org/package=tableHTML'))), 
          escape = FALSE)
```

\   

And another example:

```{r hyperlink2}
#escape needs to be set to FALSE
tableHTML(data.frame(cran = make_hyperlink(c('https://cran.r-project.org/',
                                             'https://cran.r-project.org/package=tableHTML'),
                                           c('cran', 'tableHTML'))), 
          escape = FALSE)
```

### replace_html

This is a function that can help you with very specific tasks that cannot be accompliced with the 
above functions (e.g. adding a css style to a specific cell) or with fixing a potential bug 
that we don't know about (in which case please report it on the 
[issues](https://github.com/LyzandeR/tableHTML/issues)) page. The function has been developed so 
that it works with the chaining paradigm. The function uses `sub` or `gsub` internally in order to
replace an HTML string pattern with another.

```{r replacehtml}
mtcars %>%
 tableHTML(widths = c(140, rep(45, 11))) %>%
 replace_html(' <td id="tableHTML_column_1">21</td>', 
              '<td id="mpg" style="background-color:lightyellow">21</td>')
```

\     

**Note**: A good way to work with this function is to print the table 
(`print(tableHTML(mtcars), viewer = FALSE)`), see how the part you want to
change is written and change that with the appropriate HTML text.

### Export tableHTML as a picture

If you would like to export a tableHTML as a picture, you can use the function `tableHTML_to_image()`.
This makes tableHTML compatible with MS Word and PDF (when rendering rmarkdown as pdf or word for example).
It can be also be used with plain markdown and rmarkdown but we recommend keeping the tables as HTML when working with an html document. 

**Note:** In order for the image to be taken properly you need to have `phanton_JS` installed which you can install by running 
once the following on your console: `webshot::install_phantomjs()`. `tableHTML` uses `webshot` under the hood to take the picture.

```{r picture, eval=FALSE}
mtcars %>%
  tableHTML() %>%
  tableHTML_to_image()
```

![     ](image_table1.PNG)


### Themes

The package was built to give the absolute freedom to users to design their own HTML tables the way the want.
However, we have included three categories of themes (scientific, rshiny-blue and colorize) to give the users a 
way to build nice looking tables very fast. 

You can find out more about the themes and the functions to use in our themes vignette.

### Hover and other CSS selectors

These are not supported in inline HTML but they can be added through CSS files. We can see how to 
do this in shiny below. 

## tableHTML and shiny

Now that we know about how to use the function's arguments let's see how we can use tableHTML with
shiny. The implementation is really simple since internally tableHTML uses `htmltools::HTML` to
convert the table into an HTML object. Simply using `render_tableHTML` and `tableHTML_output`
will be enough.

Let's see an example

```{r shiny1, eval=FALSE}
library(shiny)
shinyApp(
 ui = fluidPage(
   fluidRow(
    #leave some spacing
    br(),
    column(width = 1),
    tableHTML_output("mytable"))
 ),
 server = function(input, output) {
  output$mytable <- render_tableHTML(
   tableHTML(mtcars)
 )}
)
```

Or with a more complex example:

```{r shiny2, eval=FALSE}
shinyApp(
 ui = fluidPage(
   fluidRow(
    #leave some spacing
    br(),
    column(width = 1),
    tableHTML_output("mytable"))
 ),
 server = function(input, output) {
  output$mytable <- render_tableHTML(
   mtcars %>%
     tableHTML(widths = c(140, rep(45, 11)),
               second_headers = list(c(3, 4, 5), c('team1', 'team2', 'team3'))) %>%
     add_css_second_header(css = list(c('height', 'background-color', 'font-size', 'text-align'),
                                      c('40px', ' #e6e6e6', '30px', 'center')),
                           second_headers = 1:3) %>%
     add_css_header(css = list(c('height', 'background-color', 'text-align'),
                               c('30px', ' #e6e6e6', 'center')),
                    headers = 1:12) %>%
     add_css_row(css = list('background-color', '#f2f2f2'),
                 rows = even(1:34)) %>%
     add_css_row(css = list('background-color', '#e6f0ff'),
                 rows = odd(1:34)) %>%
     add_css_column(css = list('text-align', 'center'),
                    columns = names(mtcars))
 )}
)
```


## shiny and CSS

As we said previously CSS selectors cannot be used within HTML so if you use shiny you would need
to include a separate CSS file. Before we start with shiny and CSS let's see the rules applied by
tableHTML. tableHTML creates ids for columns, headers and second headers and gives the table a
specific class name as it was mentioned previously.

The rules are like this:

  * Table: Will get the class from the class argument in the function.
  * Columns: Will get an id which will be of the form tableHTML_column_x (where x
      is the column position). If rownames exist these will get the tableHTML_rownames id. If
      row groups exist these will get the tableHTML_row_groups id. Check the `add_css_column`
      function for examples.
  * Headers: Will get an id of the form tableHTML_header_x (where x is the header position).
      For example the first header will have the id tableHTML_header_1, the second header
      will have tableHTLM_header_2 and so on. If rownames exist these will get the tableHTML_header_0 id.
  * Second_Header: Will get an id of the form tableHTML_second_header_x (where x is the
      second header position). For example the first second_header will have the id tableHTML_second_header_1,
      the second header will have tableHTML_second_header_2 and so on.

Let's see this in practice. We create a CSS file e.g. mycss.css where we will write our css code.
Then we load this in R shiny in the following way: In the directory where we saved the ui.R file and
the server.R file we also create a www/ folder where we save our .css file.
In our case that is named mycss.css. We include this file in R using `includeCSS`:

```{r shinycss, eval=FALSE}
#ui.R
shinyUI(
 fluidPage(
  fluidRow(
   #leave some spacing
   br(),
   column(width = 1),
   #include css file in shiny
   includeCSS('www/mycss.css'),
   tableHTML_output("mytable"))
 )
)

#server.R
shinyServer(
function(input, output) {
   output$mytable <- render_tableHTML(
    tableHTML(mtcars, second_headers = list(c(3, 4, 5), c('col1', 'col2', 'col3')))
   )}
)
```

Note: You can find out more about CSS and shiny [here](https://shiny.rstudio.com/articles/css.html).

You can also check the [make_css](https://cran.r-project.org/package=tableHTML/vignettes/make_css.html)
function of the package which helps you create a css file and use that within shiny.

In order to add a vertical column line we can use the column ids created by tableHTML. To add a
vertical red line at mpg column, our css file would look like this:

```{css ex_1, eval=FALSE}
#tableHTML_column_1 {
	border-left: 5px solid red;
}
```

Our HTML table will look like this:

```{r css_ex1, echo=FALSE}
mtcars %>%
  tableHTML(second_headers = list(c(3, 4, 5), c('col1', 'col2', 'col3'))) %>%
  add_css_column(list('border-left', '5px solid red'), columns = 1)
```

\

In order to change the background color of one of the headers (e.g. the second) our
CSS would look like this:

```{css ex_2, eval=FALSE}
#tableHTML_column_1 {
	border-left: 5px solid red;
}

#tableHTML_header_2 {
	background-color: green;
}
```


```{r css_ex2, echo=FALSE}
mtcars %>%
  tableHTML(second_headers = list(c(3, 4, 5), c('col1', 'col2', 'col3'))) %>%
  add_css_column(list('border-left', '5px solid red'), columns = 1) %>%
  add_css_header(list('background-color', 'green'), 2)
```

\

And in order to change the color of the first second_header our css would look like:

```{css ex_3, eval=FALSE}
#tableHTML_column_1 {
	border-left: 5px solid red;
}

#tableHTML_header_2 { 
  background-color: green; 
}

#tableHTML_second_header_1 { 
 	background-color: steelblue; 
} 
```

```{r css_ex3, echo=FALSE}
mtcars %>%
  tableHTML(second_headers = list(c(3, 4, 5), c('col1', 'col2', 'col3'))) %>%
  add_css_column(list('border-left', '5px solid red'), columns = 1) %>%
  add_css_header(list('background-color', 'green'), 2) %>%
  add_css_second_header(list('background-color', 'steelblue'), 1)
```

\

You 've made it to the end of this tutorial on tableHTML! Follow the latest development on the development page on https://github.com/LyzandeR/tableHTML






