Skip to contents

You can conditionally style a table using functions that return inline styles or CSS classes. Just like with custom rendering, style functions can either be in R or JavaScript:

R functions JavaScript functions
reactable(
  iris,
  rowStyle = function(index) {
    if (iris[index, "Sepal.Width"] > 3.5) {
      list(fontWeight = "bold")
    }
  }
)
reactable(
  iris,
  rowStyle = JS("function(rowInfo) {
    if (rowInfo.values['Sepal.Width'] > 3.5) {
      return { fontWeight: 'bold' }
    }
  }")
)
  • Easier to use but more static
  • Style once, when the table is created
  • Harder to use but more dynamic
  • Style on the fly, based on client-side state

Whichever one to use depends on the situation and personal preference. You might prefer to use R functions except when you need more dynamic behavior (e.g., style based on sorted state).

Example: color scales

We can use R’s built-in color utilities to apply a color scale to a column:

data <- iris[1:5, ]
orange_pal <- function(x) rgb(colorRamp(c("#ffe4cc", "#ffb54d"))(x), maxColorValue = 255)

reactable(
  data,
  columns = list(
    Petal.Length = colDef(
      style = function(value) {
        normalized <- (value - min(data$Petal.Length)) / (max(data$Petal.Length) - min(data$Petal.Length))
        color <- orange_pal(normalized)
        list(background = color)
      }
    )
  )
)

Example: highlight sorted columns

To style sorted columns, we need to use a JavaScript function to determine whether a column is currently being sorted:

reactable(
  iris[1:5, ],
  defaultSorted = "Petal.Length",
  defaultColDef = colDef(
    class = JS("function(rowInfo, column, state) {
      // Highlight sorted columns
      for (let i = 0; i < state.sorted.length; i++) {
        if (state.sorted[i].id === column.id) {
          return 'sorted'
        }
      }
    }")
  )
)
.sorted {
  background: rgba(0, 0, 0, 0.03);
}

Cell Styling

R functions

Both style and class take an R function with up to 3 optional arguments:

colDef(
  style = function(value, index, name) {
    # input:
    #   - value, the cell value
    #   - index, the row index (optional)
    #   - name, the column name (optional)
    #
    # output:
    #   - a named list with camelCased property names
    list(color = "red", marginLeft = "30px")
    #   - or an inline style string
    "color: red; margin-left: 30px;"
  },
  class = function(value, index, name) {
    # input:
    #   - value, the cell value
    #   - index, the row index (optional)
    #   - name, the column name (optional)
    #
    # output:
    #   - CSS class names
    "class1 class2"
  }
)

Note: R functions cannot apply styles to aggregated cells.

JavaScript functions

Or a JavaScript function, wrapped in JS(), with up to 3 optional arguments:

colDef(
  style = JS("
    function(rowInfo, column, state) {
      // input:
      //  - rowInfo, an object containing row info
      //  - column, an object containing column properties (optional)
      //  - state, an object containing the table state (optional)
      //
      // output:
      //  - a style object with camelCased property names
      return { backgroundColor: 'gray' }
    }
  "),
  class = JS("
    function(rowInfo, column, state) {
      // input:
      //  - rowInfo, an object containing row info
      //  - column, an object containing column properties (optional)
      //  - state, an object containing the table state (optional)
      //
      // output:
      //  - CSS class names
      return 'class1 class2'
    }
  ")
)

rowInfo properties

Property Example Description
values { Petal.Length: 1.7, Species: "setosa" } row data values
row { Petal.Length: 1.7, Species: "setosa" } same as values (deprecated in v0.3.0)
index 20 row index (zero-based)
viewIndex 0 row index within the page (zero-based)
aggregated true whether the row is aggregated
expanded true whether the row is expanded
subRows [{ Petal.Length: 1.7, Species: "setosa" }, ...] sub rows data (aggregated rows only)
level 0 row nesting depth (zero-based)
selected true whether the row is selected

column properties

Property Example Description
id "Petal.Length" column ID
name "Petal Length" column display name
filterValue "petal" column filter value
setFilter function setFilter(value: any) function to set the column filter value (set to undefined to clear the filter)

state properties

Property Example Description
sorted [{ id: "Petal.Length", desc: true }, ...] columns being sorted in the table
page 2 page index (zero-based)
pageSize 10 page size
pages 5 number of pages
filters [{ id: "Species", value: "petal" }] column filter values
searchValue "petal" table search value
selected [0, 1, 4] selected row indices (zero-based)
pageRows [{ Petal.Length: 1.7, Species: "setosa" }, ...] current row data on the page
sortedData [{ Petal.Length: 1.7, Species: "setosa" }, ...] current row data in the table (after sorting, filtering, grouping)
data [{ Petal.Length: 1.7, Species: "setosa" }, ...] original row data in the table
meta { custom: 123 } custom table metadata from reactable() (new in v0.4.0)
hiddenColumns ["Petal.Length"] columns being hidden in the table

Row Styling

R functions

Both rowStyle and rowClass take an R function with a single argument:

reactable(
  rowStyle = function(index) {
    # input:
    #   - index, the row index
    #
    # output:
    #   - a named list with camelCased property names
    list(color = "red", marginLeft = "30px")
    #   - or an inline style string
    "color: red; margin-left: 30px;"
  },
  rowClass = function(index) {
    # input:
    #   - index, the row index
    #
    # output:
    #   - CSS class names
    "class1 class2"
  }
)

Note: R functions cannot apply styles to aggregated rows.

JavaScript functions

Or a JavaScript function with up to 2 optional arguments:

reactable(
  rowStyle = JS("
    function(rowInfo, state) {
      // input:
      //  - rowInfo, an object containing row info
      //  - state, an object containing the table state (optional)
      //
      // output:
      //  - a style object with camelCased properties
      return { backgroundColor: 'gray' }
    }
  "),
  rowClass = JS("
    function(rowInfo, state) {
      // input:
      //  - rowInfo, an object containing row info
      //  - state, an object containing the table state (optional)
      //
      // output:
      //  - CSS class names
      return 'class1 class2'
    }
  ")
)

rowInfo properties

Property Example Description
values { Petal.Length: 1.7, Species: "setosa" } row data values
row { Petal.Length: 1.7, Species: "setosa" } same as values (deprecated in v0.3.0)
index 20 row index (zero-based)
viewIndex 0 row index within the page (zero-based)
aggregated true whether the row is aggregated
expanded true whether the row is expanded
subRows [{ Petal.Length: 1.7, Species: "setosa" }, ...] sub rows data (aggregated rows only)
level 0 row nesting depth (zero-based)
selected true whether the row is selected

state properties

Property Example Description
sorted [{ id: "Petal.Length", desc: true }, ...] columns being sorted in the table
page 2 page index (zero-based)
pageSize 10 page size
pages 5 number of pages
filters [{ id: "Species", value: "petal" }] column filter values
searchValue "petal" table search value
selected [0, 1, 4] selected row indices (zero-based)
pageRows [{ Petal.Length: 1.7, Species: "setosa" }, ...] current row data on the page
sortedData [{ Petal.Length: 1.7, Species: "setosa" }, ...] current row data in the table (after sorting, filtering, grouping)
data [{ Petal.Length: 1.7, Species: "setosa" }, ...] original row data in the table
meta { custom: 123 } custom table metadata from reactable() (new in v0.4.0)
hiddenColumns ["Petal.Length"] columns being hidden in the table