How to Create a Material-UI Table Sticky Column in Only Three Lines of Code

Material-UI is a popular component library with excellent functionality and slick styling. Sometimes, however, we need just a bit more than what is available “out-of-the-box”.

Material-UI comes with a Table component with significant customizations and styling options. The Table even includes a sticky header option. However, it does not have a prop for setting ‘sticky column’. We will solve that with a quick, light-weight styling solution.

(If you are looking for how to add a sticky header, read this post).

Code Sandbox link is in the Resources section.

***UPDATE for MUI 5: Material-UI moved to a new styling API where styling is applied using the sx prop. If you are using MUI v5, simply insert the styling code directly into the sx prop instead of using makeStyles and classes. I am working on updating my articles, but until I’m finished, read my guide to the MUI sx prop to learn more.

Here’s a YouTube video version of this article, or you can watch it below:

Sticky Column CSS

sticky {
  position: "sticky",
  left: 0,
  background: "white"
}

First, let’s discuss the above CSS. Then we’ll discuss precisely which components to apply it to.

position: "sticky" means the element is treated as position: "relative" until it’s containing block crosses a specified threshold in the container it scrolls within. In simpler terms, it scrolls until it hits the edge, then sticks to the edge. See this example in the MDN docs.

left: 0 is used in tandem with position: "sticky" to inform the element where to stick at.

background: white is needed so that it appears that the other cells in each row flow under the sticky first column cell.

If you are uncertain what each property does, check out the code sandbox below and remove/add each property to get an understanding of it.

Also, you might see developers recommend a z-index of >0 for a sticky column. While that may be needed in some cases for cells to “flow under” the stuck column, it is not needed in this Material-UI Table example. It would simply depend on any additional styling applied to other table cells.


Related: Test your JavaScript proficiency with these 50 questions!


Material UI Table Sticky Column Demo

The Codesandbox below is forked straight from the “basic table” example in the Material-UI Table docs.

Here are the three most important parts:

  1. Create a css class containing the three style properties mentioned above (the class is named “sticky” in my example).
  2. In the first TableCell component in TableHead > TableRow, add the sticky class.
  3. In the first TableCell of the rows map of the TableBody, add the sticky class.

After these three things, you should have a sticky first column.

In order to demonstrate the “sticky” nature of the column, I set TableContainer maxWidth: 400.

Here’s how to style the sticky column so it stands out.

Sticky Column for Vanilla HTML table Elements

Instead of making a class, another method would be to target th:first-child. Material-UI is actually generating an HTML table, as we can see from looking at dev tools. In other words, the class method discussed above and this css selector method described here both work for making a Material-UI Table sticky column or a vanilla HTML sticky column.

Material-UI Table Sticky Column DOM
Dev Tools tells the truth

Resources

Here’s how to customize horizontal and vertical scroll on a MUI Table.

My MUI course on Udemy is now available!!! Build a full MUI app from beginning to end, learn every aspect of the sx prop, styled API, and the theme, and tackle the most challenging components! Do you want an active Q&A with me?!? Check here for coupons for my MUI course on Udemy.

View Code Sandbox Here

Here’s an enhanced Material-UI Table library called Material Table for React.

This article on sticky columns on pure HTML tables was very helpful and may be good additional reading. I have also added sticky columns to Bootstrap tables.

Here is the full code for this tutorial:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";

const useStyles = makeStyles({
  table: {
    minWidth: 650
  },
  sticky: {
    position: "sticky",
    left: 0,
    background: "white",
    boxShadow: "5px 2px 5px grey",
    borderRight: "2px solid black"
  }
});

function createData(
  name: string,
  calories: number,
  fat: number,
  carbs: number,
  protein: number
) {
  return { name, calories, fat, carbs, protein };
}

const rows = [
  createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
  createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
  createData("Eclair", 262, 16.0, 24, 6.0),
  createData("Cupcake", 305, 3.7, 67, 4.3),
  createData("Gingerbread", 356, 16.0, 49, 3.9)
];

export default function BasicTable() {
  const classes = useStyles();

  return (
    <>
      <TableContainer style={{ maxWidth: 400, border: "1px solid black" }}>
        <Table
          className={classes.table}
          aria-label="simple table"
          style={{ tableLayout: "fixed" }}
        >
          <TableHead>
            <TableRow>
              <TableCell className={classes.sticky}>
                Dessert (100g serving)
              </TableCell>
              <TableCell align="right">Calories</TableCell>
              <TableCell align="right">Fat&nbsp;(g)</TableCell>
              <TableCell align="right">Carbs&nbsp;(g)</TableCell>
              <TableCell align="right">Protein&nbsp;(g)</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {rows.map((row) => (
              <TableRow key={row.name}>
                <TableCell
                  className={classes.sticky}
                  component="th"
                  scope="row"
                >
                  {row.name}
                </TableCell>
                <TableCell align="right">{row.calories}</TableCell>
                <TableCell align="right">{row.fat}</TableCell>
                <TableCell align="right">{row.carbs}</TableCell>
                <TableCell align="right">{row.protein}</TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </TableContainer>
      <div style={{ margin: "40px", textAlign: "center" }}>
        <a
          target="_blank"
          href="https://smartdevpreneur.com/create-a-material-ui-table-sticky-column-in-only-three-lines-of-code/"
        >
          Read more about Material-UI Sticky Column here
        </a>
      </div>
    </>
  );
}
Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.