148

I'm trying to stop a table that has width explicitly declared from overflowing outside of its parent div. I presume I can do this in some way using max-width, but I can't seem to get this working.

The following code (with a very small window) will cause this:

<style type="text/css">
  #middlecol {
    width: 45%;
    border-right:2px solid red;
  }
  #middlecol table {
    max-width:100% !important;
  }
</style>

<div id="middlecol">
  <center>
    <table width="400" cellpadding="3" cellspacing="0" border="0" align="center">
      <tr>
        <td bgcolor="#DDFFFF" align="center" colspan="2">
          <strong>Notification!</strong>
        </td>
      <tr>
        <td width="50">
          <img src="http://www.example.com/img.png" width="50" height="50" alt="" border="0">
        </td>
        <td>
          Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
        </td>
      </tr>
    </table>
  </center>
 </div>

The red line is the right border of the div, and if you make your browser window small, you'll see that the table doesn't fit into it.

Adam McKenna
  • 2,295
  • 6
  • 30
  • 41
waiwai933
  • 14,133
  • 21
  • 62
  • 86
  • 3
    Off-topic: don't use `
    `. It has been deprecated for years. Besides, you already have an `align="center"` on your table.
    – ЯegDwight Feb 13 '10 at 21:55
  • 1
    This is unfortunatly something I have no control of. The content inside the div is actually included from a file that is not generated by me. I can only touch the CSS, but I would eliminate the
    if I could.
    – waiwai933 Feb 13 '10 at 22:05

13 Answers13

291

You can prevent tables from expanding beyond their parent div by using table-layout:fixed.

The CSS below will make your tables expand to the width of the div surrounding it.

table 
{
    table-layout:fixed;
    width:100%;
}

I found this trick here.

James Lawruk
  • 30,112
  • 19
  • 130
  • 137
  • 94
    This forces all of the columns to be the same width... not very useful – Serj Sagan Jul 09 '13 at 01:36
  • 17
    Actually you can still make the columns different widths, you just have to specify widths in ``s or on the first row's ``s (vs. letting it flow based on text size). From MDN: "fixed: Table and column widths are set by the widths of table and col elements or by the width of the first row of cells. Cells in subsequent rows do not affect column widths." – philfreo Jan 30 '14 at 22:58
  • 2
    Please ensure that you set `white-space: normal`. Various `white-space` settings will cause table overflow with a higher priority than `width` and `break` settings, which can be near-impossible to control. – Ben Jul 26 '22 at 07:49
  • This solution mostly works, depending on browser (as of Aug. 2022). Setting the width to 99% appears to work across all browsers. FYI. – IdahoB Aug 17 '22 at 17:32
  • My table still exceeds the viewport. Seems to be due to display:inline-block. Why is CSS such a mixture of "do it right automatically" and "only do what is specified"? The result is complexity. I would be happy with just "do what is specified", meaning that if nothing is specified, there are no spaces between or within elements. Then the page CSS would need no "normalization" and would specify all the formatting. – David Spector Jun 28 '23 at 15:06
77

A crude work around is to set display: table on the containing div.

bluish
  • 26,356
  • 27
  • 122
  • 180
questzen
  • 3,260
  • 18
  • 21
  • Just an addendum, please pay attention to the context where this being applied, this is used to impart table layout like behavior and hence the presence of other style attributes like table-row, table-cell. Tabular layouts are not floated. At time the display:table property alone is not sufficient – questzen Jul 18 '12 at 06:11
  • Also came here after hours of digging for answer. Strings for search engine: Table inside div won't scroll, firefox. Div with table won't scroll, firefox. No scrollbars appearing table inside a div. – anevaude Aug 31 '15 at 16:50
  • 2
    I have tried a few things but I just add **display:table** to the top parent div. The problem was solved, thanks. – Günay Gültekin Nov 24 '15 at 08:08
  • Best solution for the tables with long header names and long cell content. Thanks!. – Ege Bayrak Jun 20 '18 at 06:40
58

I tried all the solutions mentioned above, then did not work. I have 3 tables one below the other. The last one over flowed. I fixed it using:

/* Grid Definition */
table {
    word-break: break-word;
}

For IE11 in edge mode, you need to set this to word-break:break-all

Mr. Doomsbuster
  • 1,324
  • 13
  • 11
  • Had a table in a horizontally scrolling div that was breaking my layout because the words inside one or more of the columns were overflowing the column/table/div only on mobile phones. This helped to separate the words so that it no longer overflowed. Thank you for this it was the fix I needed after searching in my spare moments for about two days!!!! – Joel Youngberg Oct 01 '21 at 00:54
  • 1
    break-word is now deprecated – racitup Nov 11 '21 at 13:59
28

Turn it around by doing:

<style type="text/css">
  #middlecol {
    border-right: 2px solid red;
    width: 45%;
  }

  #middlecol table {
    max-width: 400px;
    width: 100% !important;
  }
</style>

Also I would advise you to:

  • Not use the center tag (it's deprecated)
  • Don't use width, bgcolor attributes, set them by CSS (width and background-color)

(assuming that you can control the table that was rendered)

bluish
  • 26,356
  • 27
  • 122
  • 180
Yvo
  • 18,681
  • 11
  • 71
  • 90
  • If i make width: 100% it ignores my margin:right. which causes horizontal bar scrolling – JayC Feb 17 '17 at 15:19
  • If content needs more than 100%, the width property is ignored. It's handled like min-width for tables. – Sebi2020 Apr 25 '22 at 13:49
16

At first I used James Lawruk's method. This however changed all the widths of the td's.

The solution for me was to use white-space: normal on the columns (which was set to white-space: nowrap). This way the text will always break. Using word-wrap: break-word will ensure that everything will break when needed, even halfway through a word.

The CSS will look like this then:

td, th {
    white-space: normal; /* Only needed when it's set differntly somewhere else */
    word-wrap: break-word;
}

This might not always be the desirable solution, as word-wrap: break-word might make your words in the table illegible. It will however keep your table the right width.

Sander Koedood
  • 6,007
  • 6
  • 25
  • 34
9

I tried almost all of above but did not work for me ... The following did

word-break: break-all;

This to be added on the parent div (container of the table .)

Waheed Asghar
  • 159
  • 1
  • 9
9
overflow-x: auto;
overflow-y : hidden;

Apply the styling above to the parent div.

Christian Heath
  • 213
  • 3
  • 8
6

If your tables are breaking out of your block-level elements, turn your container into an "inline-block" like so:

    div {
        display:inline-block;
    }

Or simply turn it into a table display type...

    div {
        display:table;
    }

This will wrap your container around your table no matter how big it grows. The advantage to using display:inline-block or display:table is they work in over 20 years worth of browsers whereas the other solutions people are posting only work in a narrow range of the newest browsers only, so will fail for many of your users. You can also set your parent container to display:table, which will "nest" your table into another table and contain it. Remember, nesting tables is also allowed in HTML and works in almost every browser ever invented!

Once you have it wrapped, you can then add more styles to control the container's width until it expands and contain the view of your table until it does need to stretch. Also, the only way to confine an expanded table and let users still see all of its content in its parent container is to also add overflow:visible or overflow:scroll. Below, as an example, I have added the width I want to constrain initially and the overflow extra...

 div {
    display:inline-block;
    overflow:scroll;
    width: 300px
}

Remember, all tables will eventually have unexpected content in their cells that could break out of containers or extend the table or page width way beyond what you expect, so setting width to "auto" is generally best for containers holding tables with unknown content sizes like images. You cannot stop tables that grow unexpectedly like this, or plan for that event, unless you have complete control over ever possible aspect of the content that fills them (which is rare). But you can control the parent that wraps around it.

And...never download and install these new JavaScript hacks or gigantic script libraries written by kids today to fix simple HTML or CSS problem developers solved 20 years ago. :)

Stokely
  • 12,444
  • 2
  • 35
  • 23
2

I used Mr. Doomsbuster's answer of using word-break: break-word; because there were long strings in the table causing it to extend beyond the containing div.

I then found break-word is deprecated.

So instead i used:

table {
    overflow-wrap: anywhere;
}
racitup
  • 416
  • 4
  • 11
  • `overflow-wrap: anywhere;` is only supported in latest browsers. For instance, safari does not support it until 15.4, so keep in mind if you need good support. – Max Jun 21 '23 at 12:11
0

You may try this CSS. I have experienced it working always.

div {
  border-style: solid;
  padding: 5px;
}

table {
  width: 100%;
  word-break: break-all;
  border-style: solid;
}
<div style="width:200px;">
  <table>
    <tr>
      <th>Col 1</th>
      <th>Col 2</th>
      <th>Col 3</th>
      <th>Col 4</th>
      <th>Col 5</th>
    </tr>
    <tr>
      <td>data 1</td>
      <td>data 2</td>
      <td>data 3</td>
      <td>data 4</td>
      <td>data 5</td>
    </tr>
    <table>
</div>
  • 2
    Please do not post identical answers to multiple questions. Instead just answer one, and comment (or flag/close vote, once you have the reputation) that the others are duplicates. For reference, I'm referring this, https://stackoverflow.com/a/63741405/2756409, https://stackoverflow.com/a/63741355/2756409, and https://stackoverflow.com/a/63741938/2756409 – TylerH Sep 04 '20 at 13:19
  • Additionally, please only provide answers that provide something new. This solution, `word-break: break-word`, has been provided by many, many answers here already. – TylerH Sep 04 '20 at 13:20
0

If anyone is struggling with this in 2023 the following might be very helpful.

We are going to make use of CSS grid, easily.

First - the parent div containing the table:

  • set the display to grid
  • set grid-template-columns to repeat(auto-fit, minmax(250px, 1fr)) (minmax first parameter can be any appropriate width you want, likewise the second param)
  • set overflow to scroll or auto

/* class name for my parent div*/
.table-responsive{
    background: #fff;
    border-radius: 5px;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    overflow-x: scroll;
    border: 1px solid #ddd;
}

/* class name for my thead and tbody*/
.table-head,
.table-body{
    white-space: nowrap;
}

/* this is extra code. You dont need it for the main issue to work*/

.custom-table{
    width: 100%;
    border-collapse: collapse;
}
.custom-table th,
.custom-table td{
    padding: 0.5rem 1rem;
    text-align: left;
}
<div class="table-responsive">
    <table class="custom-table">
        <thead class="table-head">
            <tr>
              <th scope="col">#</th>
              <th scope="col">Client Name</th>
              <th scope="col">Service</th>
              <th scope="col">Style</th>
              <th scope="col">Contact</th>
              <th scope="col">Date Booked</th>
              <th scope="col">Time Booked</th>
              <th scope="col">Booking Fee</th>
              <th scope="col">Booked On</th>
              <th scope="col">Action</th>
            </tr>
        </thead>

        <tbody class="table-body">
            <tr> 
              <td scope="row">1</td>
              <td scope="row">Some client name here</td>
              <td scope="row">Some service name or type</td>
              <td scope="row">Some style</td>
              <td scope="row">some email or phone</td>
              <td scope="row">something here</td>
              <td scope="row">something here</td>
              <td scope="row">something here</td>
              <td scope="row">something here</td>
              <td scope="row">something here</td>
            </tr>
            <tr> 
              <td scope="row">1</td>
              <td scope="row">Some client name here</td>
              <td scope="row">Some service name or type</td>
              <td scope="row">Some style</td>
              <td scope="row">some email or phone</td>
              <td scope="row">something here</td>
              <td scope="row">something here</td>
              <td scope="row">something here</td>
              <td scope="row">something here</td>
              <td scope="row">something here</td>
            </tr>
        </tbody>
    </table>
</div >

NB: at this point your table should properly fit into its parent div, and scroll where necessary.

If you don't like the content of the table heads (th) and table body (td) to wrap or break, then the second step is ideal:

Second - the thead and tbody

  1. set both the thead (use any class you give it) and tbody to white-space: nowrap

Just like that you are cool to go.

Prosper
  • 19
  • 1
-3

There's a width="400" on the table, remove it and it will work...

bluish
  • 26,356
  • 27
  • 122
  • 180
dale
  • 760
  • 5
  • 11
-3

Put it in <TableContainer /> like blow

import { TableContainer, Table } from '@mui/material';


export default myTable = () => {

    return (
        <TableContainer>
            <Table>
                // ...
            </Table>
        </TableContainer>
    )
}


Bambier
  • 586
  • 10
  • 16