How to Customize Material-UI Table Cell Width and Styling

Customizing Material-UI Table Cell width is a common requirement. Precisely styling the TableCell component is also often requested by users. In this demo, I will show how to create a table sized with fixed width or a dynamic width that fits to the contents of the table cells. I will also set TableCell hover color, padding, and cell border, and add a border around the Table. Finally, I will inject a button into the first column of each row.

Below is the table you will build. First you will learn several nuances of setting cell width. Once the table cells have their widths we will set the width of the TableContainer to be dynamically fit to the total of the cell widths. Then we’ll dive into styling.

The Code Sandbox for the pictured table is Resources section of the article.

Material-UI Table Cell Width and Styling
Material-UI Table Cell Width and Styling

These MUI posts will also be helpful:

Here is a link to a YouTube video of setting table cell width, or you can watch below:

MUI TableCell Width

Let’s take a look at the five TableCell components in the TableHead component. For four of the cells, width is set to 100px with inline style.

On the fifth cell, however, width is specified at 25%. Interestingly, the browser dynamically calculates a total width of the table and required cell width to allocate 25% of the width to the cell. I.E. if the first four cells are 100px each, the fifth cell will get a width of 133px for a total table width of 533px. 133 is 25% of 533.

const useStyles = makeStyles({
  tableCell: {
    padding: "0px 12px 0px 0px"
  }
});

//...
//In the JSX return
<TableCell 
  className={classes.tableCell} 
  style={{ width: 100 }}>
  Food
</TableCell>
<TableCell
  className={classes.tableCell}
  style={{ width: 100 }}
  align="right"
>
  Calories
</TableCell>
<TableCell
  className={classes.tableCell}
  style={{ width: 100 }}
  align="right"
>
  Fat
</TableCell>
<TableCell
  className={classes.tableCell}
  style={{ width: 100 }}
  align="right"
>
  Carbs
</TableCell>
<TableCell
  className={classes.tableCell}
  style={{ width: "25%" }}
  align="right"
>
  Protein
</TableCell>

Related: Check out Material Table for React, a Table library built directly on top of Material-UI’s table.


Material-UI Table Column Width

Is it possible to set width at a column level for Material-UI tables? Essentially, the answer is “yes” because the TableCell components act as a proxy for the column.

MUI Tables are constructed in a table -> row -> cell pattern and use children components instead of a column prop to scaffold the table. A brief example is below.

<Table>
  <TableRow>
    <TableCell/>
    <TableCell/>
    <TableCell/>
  </TableRow>
</Table>

However, consider how the cells behave. You code them once, and each behaves the same for every replication in every row. This means the TableCell is acting as a column.

As shown in the previous section, simply use the style or classes prop on the TableCell to set the width, i.e. style={{ width: "25%" }}. ***Update for MUI v5: check out the new sx prop, which is preferred over style and classes.

As info, MUI DataGrids are column based and make use of a column prop instead of children cell components.

React-Bootstrap tables set column width at the cell level just like MUI tables.

MUI Dynamic or Fixed TableContainer Width

Now that we have a set width for our five TableCell components, let’s make sure the TableContainer isn’t overriding our cell width.

By default, TableContainer will be width: 100%. This will ignore our cell widths and force the cells to stretch with the container. This can be difficult to override.

The best way I have found to override the default TableContainer behavior is with Styled Components:

const StyledTableContainer = withStyles((theme) => ({
root: {
width: "max-content"
}
}))(TableContainer);

Using withStyles, we create a new component based on the TableContainer. The difference is we have targeted the root and have set width: "max-content”. Max-Content sizes a component based on its contents, which is precisely what we want here.

Max-Content is supported by Chrome, Edge, and has partial support in FireFox.

After creating the StyledTableContainer, simply use it in the return statement like so:

<StyledTableContainer component={Paper}>
<Table fixedHeader={false} style={{ tableLayout: "auto" }}>
<TableHead>
<TableRow>
<TableCell className={classes.tableCell} style={{ width: 100 }}>
Food
</TableCell>
//...more JSX

If you need a fixed width, you could use Styled Components for that as well.

If you want the first column to be a sticky column, that can be accomplished in only three lines of code.

MUI Table Cell Hover, Buttons, and More Styling

Simply to show another method of overriding components, I created a StyledTableCell component and added hover functionality:

const StyledTableCell = withStyles((theme) => ({
  root: {
    padding: "0px 12px 0px 0px",
    "&:hover": {
      backgroundColor: "red"
    }
  }
}))(TableCell);

Notice the JSS syntax for implementing hover. There is no space between the & and :hover. That means the hover pseudo-class is directly applied to the same element that the root class is applied to, it’s not applied to a child element.

Cell padding is also included in this component.

Theoretically I could move this component into it’s own file and import it wherever I wanted this custom cell hover. It’s common to use Styled Components as part of a theme. Using it is like using TableCell:

<StyledTableCell align="right">{row.calories}</StyledTableCell>

Button is simple to add inside of the TableCell:

<StyledTableCell component="th" scope="row">
  <Button
  variant="outlined"
  style={{
    width: "100%",
    backgroundColor: "rgba(0,0,0,0.1)"
  }}
  >
    {row.name}
  </Button>
</StyledTableCell>

I simply added inline styling to achieve Button backgroundColor. This could also have been done via a class. As info, the color is black with opacity 0.1.

MUI Table Border and TableCell Border

Finally, to add a border to the Table, take the TableContainer JSX and simply update it with a class or some inline styling like so:

<StyledTableContainer
  component={Paper}
  style={{ border: "1px solid rgba(0,0,0,0.2)", padding: 4 }}
>

Once again, I’ve given the Table a border that is black with a small amount of opacity.

I also gave the first data column a right border. The borderRight styling is set at the cell level using a class.

cellBorderRight: {
  borderRight: "1px solid rgba(0,0,0,0.2)"
}

Notice that I’ve also set the padding of the tableCell class to 12px on the right, and same with the the StyledTableCell, so that the border is spaced away from the text..

Read here how to add additional styling to the MUI Table.

Resources

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.

This MUI tutorial shows an app with Form input and Table output.

Code Sandbox with full React code.

Sometimes customizing Material-UI components can be pretty challenging. This thread provides an insight into how many people struggled with getting cell and table width to their desired specifications.

Share this post:

Leave a Comment

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