DataFrame 1.0 Help

toHtml

HTML rendering

DataFrame instances can be rendered to HTML. Rendering of hierarchical tables in HTML is supported by JS and CSS definitions that can be found in project resources.

Dataframes can also be formatted before being converted to HTML. See format for how to do this.

Besides that, DataFrame provides multiple APIs to customize HTML output.

Display images

Values of the org.jetbrains.kotlinx.dataframe.datatypes.IMG class are rendered as an <img> tag

val htmlData = dataFrameOf( "kotlinLogo" to columnOf( IMG("https://kotlin.github.io/dataframe/images/kotlin-logo.svg"), ), ).toStandaloneHtml()

Embed pages

Values of the org.jetbrains.kotlinx.dataframe.datatypes.IFRAME class are rendered as an <iframe> tag

val htmlData = dataFrameOf( "documentationPages" to columnOf( IFRAME( src = "https://kotlin.github.io/dataframe/tohtml.html", width = 850, height = 500, ), ), ).toStandaloneHtml()

Values of java.net.URL are rendered as <a> tag

val htmlData = dataFrameOf( "documentationPages" to columnOf( URI("https://kotlin.github.io/dataframe/format.html").toURL(), URI("https://kotlin.github.io/dataframe/tohtml.html").toURL(), URI("https://kotlin.github.io/dataframe/jupyterrendering.html").toURL(), ), ).toStandaloneHtml()

Render any HTML inside a cell

Wrap cell values in custom HTML using RenderedContent.media

val htmlData = dataFrameOf( "documentationPages" to columnOf( "https://kotlin.github.io/dataframe/format.html", "https://kotlin.github.io/dataframe/tohtml.html", "https://kotlin.github.io/dataframe/jupyterrendering.html", ), ) .convert { documentationPages }.with { val uri = URI(it) RenderedContent.media("""<a href='$uri'>${uri.path}</a>""") } .toStandaloneHtml()
val htmlData = dataFrameOf( "documentationPages" to columnOf( "https://kotlin.github.io/dataframe/format.html", "https://kotlin.github.io/dataframe/tohtml.html", "https://kotlin.github.io/dataframe/jupyterrendering.html", ), ) .convert { "documentationPages"<String>() }.with { val uri = URI(it) RenderedContent.media("""<a href='$uri'>${uri.path}</a>""") } .toStandaloneHtml()

Sample data

This dataframe is used in the following examples

val df = dataFrameOf( "name" to columnOf( "firstName" to columnOf("Alice", "Bob", "Charlie", "Charlie", "Bob", "Alice", "Charlie"), "lastName" to columnOf("Cooper", "Dylan", "Daniels", "Chaplin", "Marley", "Wolf", "Byrd"), ), "age" to columnOf(15, 45, 20, 40, 30, 20, 30), "city" to columnOf("London", "Dubai", "Moscow", "Milan", "Tokyo", null, "Moscow"), "weight" to columnOf(54, 87, null, null, 68, 55, 90), "isHappy" to columnOf(true, true, false, true, true, false, true), )

Reusable rendering logic

Generic approach to custom cell rendering. Useful if you want to apply the same rendering to different dataframes.

class CustomArrayCellRenderer : ChainedCellRenderer(DefaultCellRenderer) { override fun maybeContent(value: Any?, configuration: DisplayConfiguration): RenderedContent? { if (value is Boolean) { return RenderedContent.text(if (value) "✓" else "✗") } // return null to delegate work to parent renderer: DefaultCellRenderer return null } override fun maybeTooltip(value: Any?, configuration: DisplayConfiguration): String? { // return null to delegate work to parent renderer: DefaultCellRenderer return null } } val htmlData = df.toStandaloneHtml(cellRenderer = CustomArrayCellRenderer())

Custom HTML outside the table

The result of toHtml can be composed with other HTML, CSS, or JS definitions. Let's build an alternative to displaying all rows in one table: custom pagination across multiple files

val pages = df.duplicateRows(10).chunked(20) val files = pages.indices.map { i -> File("page$i.html") } val navLinks = files.mapIndexed { i, file -> """<a href="${file.name}">Page ${i + 1}</a>""" }.joinToString(" | ") pages.forEachIndexed { i, page -> val output = files[i] page.toStandaloneHtml().plus(DataFrameHtmlData(body = navLinks)) // uncomment // .writeHtml(output) }

Custom style and scripts

Let's add a hover effect and click listener for table cells. See init.js and table.css for reference.

val selectCellInteraction = DataFrameHtmlData( style = """ td:hover { background-color: rgba(0, 123, 255, 0.15); cursor: pointer; } """.trimIndent(), script = """ (function() { let cells = document.querySelectorAll('td'); cells.forEach(function(cell) { cell.addEventListener('click', function(e) { let content = cell.textContent; alert(content); }); }); })(); """.trimIndent(), ) // keep in mind JS script initialization order. val htmlData = df.toStandaloneHtml().plus(selectCellInteraction)

Depending on your environment, there can be different ways to use the result of toHtml functions.

IntelliJ IDEA

Working with the result

The following function produces HTML that includes JS and CSS definitions. It can be displayed in the browser and has parameters for customization.

val configuration = DisplayConfiguration(rowsLimit = null) df.toStandaloneHtml(configuration).openInBrowser() df.toStandaloneHtml(configuration).writeHtml(File("/path/to/file")) df.toStandaloneHtml(configuration).writeHtml(Path("/path/to/file"))

Composing multiple tables

toHtml and toStandaloneHtml return composable DataFrameHtmlData, which you can use to include additional scripts, elements, or styles at the end of the page or just to merge multiple tables into one HTML snippet.

val df1 = df.reorderColumnsByName() val df2 = df.sortBy { age } val df3 = df.sortByDesc { age } listOf(df1, df2, df3).fold(DataFrameHtmlData.tableDefinitions()) { acc, df -> acc + df.toHtml() }
val df1 = df.reorderColumnsByName() val df2 = df.sortBy("age") val df3 = df.sortByDesc("age") listOf(df1, df2, df3).fold(DataFrameHtmlData.tableDefinitions()) { acc, df -> acc + df.toHtml() }

Jupyter Notebooks

Configuring display for individual output

toHtml is useful if you want to configure how a single cell is displayed. To configure the display for the entire notebook, please refer to the Jupyter Notebooks section.

df.toHtml(DisplayConfiguration(cellContentLimit = -1))
08 December 2025