mui / material-ui

Material UI: Ready-to-use foundational React components, free forever. It includes Material UI, which implements Google's Material Design.
https://mui.com/material-ui/
MIT License
91.86k stars 31.57k forks source link

[Table] Set table column width #1911

Closed celiao closed 8 years ago

celiao commented 8 years ago

Is it possible to set the width of Table columns?

StackOverflow equivalent question: https://stackoverflow.com/questions/51216285/material-ui-v1-set-table-column-widths

kamek-pf commented 8 years ago

Nothing quite special about this :

<TableCell style={{ width: '2rem' }}>
max-ch9i commented 8 years ago
<TableRowColumn style={{ width: 100 }}>

doesn't behave too well with TableHeaderColumn

zikangyao commented 8 years ago

Is there any way to dynamically assign the width of col based on content ?

sanfilippopablo commented 7 years ago

In my vanilla HTML table, the columns width are automatically set depending on content. material-ui seems to enforce equal width on all columns. Is there a way to set width of column to be dynamic instead, like vanilla HTML tables?

qettnqs commented 7 years ago

@sanfilippopablo, <Table> uses the table-layout: 'fixed' css prop, leading to all columns having the same width, combined with white-space: 'nowrap' on every table cell to handle the overflow.

You can't safely switch to table-layout: 'auto' since the table then grows infinitely with its content unless you remove the above-mentioned white-space css prop. And if you do this, you can't use the fixedHeader={true} prop anymore since headers are then contained in a separate table :cry:.

Some feedback would be appreciated.

theseancronin commented 7 years ago

What I've been doing to set the widths of columns is for the

style, set table-layout to auto, as mentioned above, then I give widths in percentages to my columns. i.e. width 30% and width 70%. This would be a two-column layout example, with table header columns in first first column rather than in the header..

HeWasntOffByMuch commented 7 years ago

You can't safely switch to table-layout: 'auto' since the table then grows infinitely with its content

What about adjusting table header width when the tableRowColumn width changes with content? I can't seem to set it up so those 2 are aligned.

qettnqs commented 7 years ago

I guess you either use fixedHeader={true} and can't set a custom width or you don't and have to keep your headers inside your <TableBody>.

HeWasntOffByMuch commented 7 years ago

Okay, putting header in tbody works! Now I need to figure out how to do multi-line header columns. Any tips?

qettnqs commented 7 years ago

Are you trying to achieve something like this? (if not, you can probably find the right example in this website)

I think you can do pretty much everything you want with the attributes colSpan on TableHeaderColumn and TableRowColumn and rowSpan on TableRow.

NZhuravlev commented 7 years ago

I don't understand - why is this closed?

henrycity commented 7 years ago

Putting TableHeader in TableBody doesn't work for me.

HeWasntOffByMuch commented 7 years ago

@tvtri96 What we suggested was putting tableRow acting as tableheader in tableBody, but it looks to me like it is now working fine.

this is how it looks now in my code:

<Table fixedHeader={true}>
          <TableHeader>
            <TableHeaderComponent schema={schema}/>
          </TableHeader>
          <TableBody displayRowCheckbox={false} showRowHover={true}>
            {this.props.data.map((item, index) => (
              <TableRowComponent key={index} schema={this.props.schema}
                item={item} onRemoveClick={this.handleRemoveItem}
                onEditClick={this.handleEditItem}
              />
            ))}
          </TableBody>
</Table>

and header columns are aligned with body columns correctly.

henrycity commented 7 years ago

Tks for answering me. What is inside TableHeaderComponent? I guess it is not like a normal TableHeader right?


<TableHeader fixedHeader={true} >
     <TableRow>
          <TableHeaderColumn>Timestamp</TableHeaderColumn>
     </TableRow>
 </TableHeader>
HeWasntOffByMuch commented 7 years ago

Yes, its just wrapped for reasons.

damianobarbati commented 7 years ago

Any news on this? How can I let the columns auto-adjust to content?

arjan commented 7 years ago

This works for me, auto-sizing:

      <Table style={{tableLayout: 'auto'}}>
musray commented 6 years ago

@arjan

 <Table style={{tableLayout: 'auto'}}>

This has no effect on header.

sonaye commented 6 years ago

<Table fixedHeader={false} style={{ tableLayout: 'auto' }}> works (dynamic sizing based on content).

devuxer commented 6 years ago

I needed to add width: "auto", which results in:

<Table fixedHeader={false} style={{ width: "auto", tableLayout: "auto" }}>
devuxer commented 6 years ago

@nathanmarks, Please reopen.

Table should have a built-in property to allow it to auto-size to contents, and it should not require disabling fixedHeader. I would go further and say auto-size to contents should be the default behavior.

mbrookes commented 6 years ago

@devuxer Sorry, but we aren't proactively adding features to the v0.x branch.

devuxer commented 6 years ago

@mbrookes, Thanks for letting us know. Are you saying the Table in v1.x solves this issue?

mbrookes commented 6 years ago

@devuxer I beleive so, it was rewritten from the ground up.

https://material-ui.com/demos/tables/

okanthony commented 6 years ago

I had a table with three columns, where the first and third columns would always contain a small amount of text. I wanted the second column to take up the bulk of the space so the first and third columns would be pushed to the left and right edges of the table, respectively. This worked for me (using style here as opposed to className for brevity):

<Table style={{ tableLayout: "auto" }} />
<TableRowColumn style={{ width: "10%" }}>{text}</TableRowColumn>
<TableRowColumn style={{ width: "80%" }}>{text}</TableRowColumn>
<TableRowColumn style={{ width: "10%" }}>{text</TableRowColumn>
witm55 commented 6 years ago

I found a better solution... so, every column has the same width. Let's say I have three colums, and I want the first one to take up half of the overall width, and the third should be about one third of the row; the one in the middle be the smallest one:

  <TableRowColumn colSpan='3'>twice as big!</TableRowColumn>
  <TableRowColumn> I'm small</TableRowColumn>
  <TableRowColumn colSpan='2'>I'm in between</TableRowColumn>

Actually, I have 7 columns, but the sum of my colspans equals 20 - the last one only holds an icon for deletion, most of the other ones are colspan 3 - the large text field is colspan 6, and a selectfield and a datepicker are on colspan 2...

Works like a charm!

kuzdogan commented 5 years ago

This is good to go in v1 or above

const styles = { 
  narrowCell: {
    'width': '150px',
  }
};

<Table>
  <TableHead>
    <TableRow>
      <TableCell>Company Name</TableCell>
      <TableCell style={classes.narrowCell} numeric>Amount</TableCell>
    </TableRow>
  </TableHead>
  <TableBody>
  <TableRow>
    <TableCell> name 1 </TableCell>
    <TableCell style={classes.narrowCell}> $100 </TableCell>
  </TableRow>
  </TableBody>
</Table>

Can also give percentage widths, rest of the cells span equally

Bowfish commented 5 years ago

How can I use this solution if I have to use colspan={2} in a TableHead row?

If I add colspan={2} all cols will have the same width. Something like this:

const styles = { 
    narrowCell: {
        'width': '150px',
    },
    miniCell: {
        'width': '75px',
    },
};

<Table>
    <TableHead>
        <TableRow>
            <TableCell>Company Name</TableCell>
            <TableCell className={classes.narrowCell} numeric colspan={2}>Amounts</TableCell>
        </TableRow>
    </TableHead>
    <TableBody>
    <TableRow>
        <TableCell> name 1 </TableCell>
        <TableCell className={classes.miniCell}> $100 </TableCell>
        <TableCell className={classes.miniCell}> $100 </TableCell>
    </TableRow>
    </TableBody>
</Table>
kuzdogan commented 5 years ago

@Bowfish If you want to change colspan={2} cell width try changing the table width, given it spans the whole table. Smaller cells can be adjusted individually.

pouriaMaleki commented 5 years ago

Applying this style somehow helped me: I just sat different maxWidth for different cels in row but same in each column using inline styles.

const styles = (theme) => ({
  tableCell: {
    whiteSpace: 'nowrap',
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    maxWidth: '40px',
  },
});
abhisheksoni27 commented 5 years ago

None of the solutions posted above work. Why is this so difficult to achieve?

emersonbottero commented 5 years ago
  <Table fixedHeader={false} style={{tableLayout: "auto" }}>
        <colgroup>
            <col width="250px" />
            <col />
            <col width="40px" />
            <col width="40px" />
        </colgroup>
        <TableHead>
          <TableRow>

the second collumn is flex

devenovil commented 5 years ago

None of the solutions posted above work. Why is this so difficult to achieve?

Somehow i recognize why it's not work, because we only set width only forTableHead or TableBody! To make it work, we should define minWidth and maxWidth bot on TableCell in TableHead and TableBody, here the example

<Table>
    <TableHead>
        <TableRow>
            <TableCell column='data1' style={{minWidth:100, maxWidth:100}}>{content}</TableCell>
            <TableCell column='data2' style={{minWidth:'200px', maxWidth:'200px'}}>{content}</TableCell>
        </TableRow>
    </TableHead>
    <TableBody>
            <TableRow>
            <TableCell column='data1' style={{minWidth:100, maxWidth:100}}>{content}</TableCell>
            <TableCell column='data2' style={{minWidth:200, maxWidth:200}}>{content}</TableCell>
            </TableRow>
    </TableBody>
</Table>

As you can see, we can use both value for style by integer and string. But for string, it's only work if you defined it by px, if you use percentage, like minWidth:'25%', it's not gonna work, i already try it.

Why do i use both of minWidth and maxWidth? Not width? Because I already try it, if you want to make your column with fixed width, you must use minWidth and maxWidth instead of width. I didn't know why, but widthseems not work to solve this problem.

Note : Both of TableCell in TableHead and TableBody that contain same data, must have same style!

I hope this code help you guys, cheers

pfftdammitchris commented 5 years ago

I literally set width: 10%, minWidth: 10% and maxWidth: 10% to every single TableCell including the ones under table headers. I then proceeded to create <colgroup>..etc elements and applied the same styles to them as well. i also set the Table element to tableLayout: auto and width: auto. i tried every single solution in this thread and combined them all to this one final output. in addition, i also utilized the "inspect element" tool in chrome and hacked every single element on the table to use width: 10% min-width: 10% and max-width: 10%. this was also reflected in the React inspecter in devtools. it literally showed me all the elements ive changed as "width 10%" etc.

result: still doesnt adjust the widths of columns

i think it is safe to assume now that there is actually an impossible that exists. and it is in this very thread

Edit:

I actually ended up doing something that was against what people in this thread were suggesting... i set autoLayout: fixed in my table and it started working. What in the world is this black magic

Ericnr commented 5 years ago

Also having a bad time trying to set widths. Had to set the select checkbox width: 0.01% for it to stay at a reasonable width, nothing else works

claytongulick commented 4 years ago

For those stuck on the old version of this and struggling with the footer, adding fixedFooter={false} to @devenovil 's solution works for me.

pbassut commented 4 years ago

@nathanmarks Can you at least clarify why you closed this? This should be a very recurrent required feature.

yanivfranco commented 4 years ago

@pbassut is right. This is a very basic feature for a table component... Is there any update? Or an explanation why it is so problematic to implement...

crizant commented 4 years ago

@devenovil Instead of maxWidth, if you want to use %, you can use width like:

<TableCell style={{ width: '35%' }}>
  Table Data
</TableCell>
<TableCell>
  Another Table Data
</TableCell>
benjaminaaron commented 4 years ago

For me it worked to set the width only for the cells in the header: <TableCell width={props.colWidths[index] + '%'}>, this results in the columns for the entire table behaving as expected.

smcalilly commented 4 years ago

I set the column widths with the percentage and it sort of works, but for some reason, it adds a phantom column on the far right. Via inspecting the element, it appears to add a "TableStubCell" element to the table. I have no idea where that came from.

I've had similar issues with other MUI tables, and my work-arounds are never that great. Would be cool if y'all opened up this issue and fixed it...clearly other folks are struggling with it too.

edit: the TableStubCell came from the dx-react-grid-material-ui npm package, so sorry for pointing fingers!

aprilmintacpineda commented 4 years ago

My solution is to do

<Table>
  <TableHeader>
    <TableRow>
      <TableCell>
        <Box width="200px">
          User Fullname
        </Box>
      </TableCell>
      {/* ...rest of the columns */}
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>
        April Mintac Pineda
      </TableCell>
      {/* ...rest of the columns */}
    </TableRow>
    {/* ...rest of the rows */}
  </TableBody>
</Table>

But would be nice if we could just do

<Table>
  <TableHeader>
    <TableRow>
      <TableCell width="200px">
        User Fullname
      </TableCell>
      {/* ...rest of the columns */}
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>
        April Mintac Pineda
      </TableCell>
      {/* ...rest of the columns */}
    </TableRow>
    {/* ...rest of the rows */}
  </TableBody>
</Table>
nazrulcsebd commented 4 years ago

This works for me with the version "@material-ui/core": "4.9.0"

    <TableContainer className={classes.container}>
              <Table className={classes.table} stickyHeader size="small">
                <TableHead>
                  <TableRow>
                    <TableCell width="30%">User Name</TableCell>
                    <TableCell width="20%">Designation</TableCell>
                    <TableCell width="10%">Nid</TableCell>
                    <TableCell width="20%">Email</TableCell>
                    <TableCell width="10%">Mobile</TableCell>
                    <TableCell width="10%">Gender</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {props.isGridLoading && (
                    <TableRow>
                      <TableCell colSpan={6}>
                        <LoadingGridSpinner open={props.isGridLoading} />
                      </TableCell>
                    </TableRow>
                  )}

                  {props.profileObj.lists &&
                    props.profileObj.lists.map(row => (
                      <TableRow key={row.userProfileId} hover={true}>
                        <TableCell width="30%">
                          {row.userName}
                        </TableCell>
                        <TableCell width="20%">{row.designation}</TableCell>
                        <TableCell width="10%">{row.nid}</TableCell>
                        <TableCell width="20%">{row.email}</TableCell>
                        <TableCell width="10%">{row.mobile}</TableCell>
                        <TableCell width="10%">{row.gender}</TableCell>
                      </TableRow>
                    ))}
                </TableBody>
              </Table>
ydax commented 4 years ago

The approach used by @nazrulcsebd and @crizant worked for me. Here's my code:

<TableContainer component={Paper} style={{ marginTop: 10 }}>
          <Table style={{ width: 'auto', tableLayout: 'auto' }}>
          <TableHead>
            <TableRow>
              <TableCell>Team Member</TableCell>
              <TableCell align="left">Level</TableCell>
              <TableCell align="left">Last Login</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            { tableArray.map(({ id, name, accessLevel, login }) => (
              <TableRow key={id}>
                <TableCell component="th" scope="row" style={{ width: '35%' }}>
                  {name}
                </TableCell>
                <TableCell align="left">{accessLevel}</TableCell>
                <TableCell align="left">{login}</TableCell>
              </TableRow>
            ))
          }
          </TableBody>
        </Table>
      </TableContainer>
binajmen commented 4 years ago

In my case I wanted to have the smallest column possible to hold an "action" button at the end of the table. Adding style={{ width: 1 }} to the TableCell in TableHead did the trick.

        <TableContainer component={Paper}>
            <Table className={classes.table} aria-label="simple table">
                <TableHead>
                    <TableRow>
                        {header.map((th, i) => (
                            <TableCell key={i}>{th}</TableCell>
                        ))}
                        <TableCell style={{ width: 1 }}>actions</TableCell>
                    </TableRow>
                </TableHead>
                <TableBody>
                    {data.map((row, i) => (
                        <TableRow key={i} hover>
                            {header.map((h, i) => (
                                <TableCell key={i} align="left">{row[h]}</TableCell>
                            ))}
                            <TableCell>
                                <IconButton aria-label="edit">
                                    <MoreHorizIcon fontSize="small" />
                                </IconButton>
                            </TableCell>
                        </TableRow>
                    ))}
                </TableBody>
            </Table>
        </TableContainer>
KristiyanTs commented 4 years ago
const useStyles = makeStyles(theme => ({
  table: {
    "& tr:nth-child(2), & td:nth-child(2) {
      width: '32px',
    }
  }
}));

And then, use the style in the root of the table

 <Table
     ....
     className={classes.table}
>

Haven't tested much yet (Fixed header, etc)

guifeliper commented 4 years ago

it would be much better if we can just give the same 12 column system to tables for example:

   <TableContainer component={Paper}>
      <Table className={classes.table} aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell>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 component="th" scope="row" xs={4}>
                {row.name}
              </TableCell>
              <TableCell align="right" xs={2}>{row.calories}</TableCell>
              <TableCell align="right" xs={2}>{row.fat}</TableCell>
              <TableCell align="right" xs={2}>{row.carbs}</TableCell>
              <TableCell align="right" xs={2}>{row.protein}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
Aditya94A commented 3 years ago

Does anyone know a way to let the table scroll in x direction if there are too many columns? I'm only able to make this happen by giving minWidth=something hardcoded (which is not great for unknown number of columns)

It seems like fixedHeader={false} style={{width: "auto", tableLayout: "auto"}} are ignored in the latest version.

Any ideas?

repetitioestmaterstudiorum commented 3 years ago

I ended up with a workaround using a list element inside the table, and defining the width of the list item... Something like:

<TableCell>
  <ul style={{ width: "150px" }}>
    <li>{row.whatever}</li>
    <li>{row.whatever1}</li>
    <li>{row.whatever2}</li>
  </ul>
</TableCell>
aprilmintacpineda commented 3 years ago

2020 and still hard to achieve, the weirdest part is that I try to set the width of a column, the other columns automatically adjust themselves even when I also defined width for them! what gives? It's like the table is making sure the whole table's width doesn't go beyond 100% this is giving me a hard time. If I was not using material-ui's table this would be very very easy, seems material UI only made it hard?