343

I've got a simple table that is used for an inbox as follows:

<table border="1">
     <tr>
        <th>From</th>
        <th>Subject</th>
        <th>Date</th>
    </tr>
</table>

How do I set the width so the From and Date are 15% of the page width and the Subject is 70%. I also want the table to take up the whole page width.

13 Answers 13

556

You can set the width of a table column using the CSS width property of the col element. The width value is most commonly specified in pixels (width: 200px;), or as a percentage of the width of the parent element (width: 50%;). Example with inline style attribute:

<table style="width: 100%">
    <colgroup>
       <col span="1" style="width: 15%;">
       <col span="1" style="width: 70%;">
       <col span="1" style="width: 15%;">
    </colgroup>
    
    
    
    <!-- Put <thead>, <tbody>, and <tr>'s here! -->
    <tbody>
        <tr>
            <td style="background-color: #777">15%</td>
            <td style="background-color: #aaa">70%</td>
            <td style="background-color: #777">15%</td>
        </tr>
    </tbody>
</table>

13
  • 9
    Like the cleanliness of this solution. However, please close out the col e.g <col span="1" style="width: 15%;" /> or <col span="1" style="width: 15%;"></col>
    – lsu_guy
    Commented Aug 25, 2013 at 0:22
  • 40
    @Isu_guy you only close <col> when using XHTML -- in HTML, <col> tag has no closing... see link for more info. In HTML5, <col> is a void element, meaning it MUST NOT be closed Commented Aug 31, 2013 at 14:22
  • 5
    @Zulu according to w3schools.com/tags/att_col_width.asp "The <col> width attribute is not supported in HTML5."
    – Caltor
    Commented Nov 5, 2013 at 13:46
  • 51
    @Caltor: the code is not using the <col> width attribute; it is using a CSS *style* width, which is what replaced the <col> width attribute. (despite the multiple people up-voting that comment!!) Commented Aug 2, 2014 at 19:02
  • 16
    span="1" is superfluous since 1 is the default.
    – Madbreaks
    Commented Jan 4, 2017 at 21:28
174

table {
  width: 100%;
  border: 1px solid #000;
}
th.from, th.date {
  width: 15%
}
th.subject {
  width: 70%; /* Not necessary, since only 70% width remains */
}
<table>
  <thead>
    <tr>
      <th class="from">From</th>
      <th class="subject">Subject</th>
      <th class="date">Date</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>[from]</td>
      <td>[subject]</td>
      <td>[date]</td>
    </tr>
  </tbody>
</table>

The best practice is to keep your HTML and CSS separate for less code duplication, and for separation of concerns (HTML for structure and semantics, and CSS for presentation).

Note that, for this to work in older versions of Internet Explorer, you may have to give your table a specific width (e.g., 900px). That browser has some problems rendering an element with percentage dimensions if its wrapper doesn't have exact dimensions.

4
  • 1
    this solution fails if you have colspans in the first row
    – mark1234
    Commented Aug 13, 2015 at 15:52
  • 8
    Good because <col width=""> is obsolete in HTML5: developer.mozilla.org/en/docs/Web/HTML/Element/col
    – Richard
    Commented Feb 24, 2017 at 12:19
  • I had to use min-width. Commented Oct 9, 2021 at 22:46
  • I had to use min-width instead of width for it to work, but overall great, thanks.
    – K.Mat
    Commented Oct 13, 2022 at 9:35
42

Use the CSS below, the first declaration will ensure your table sticks to the widths you provide (you'll need to add the classes in your HTML):

table{
  table-layout:fixed;
}
th.from, th.date {
  width: 15%;
}
th.subject{
  width: 70%;
}
2
  • Actually you only need to specify width of the two columns. The third one will be calculated automatically, so table{table-layout:fixed};.from,.date{width:15%} is enough. Unless the classes are used on other elements too, writing th.from is redundant and can be shortened to just .from.
    – tomasz86
    Commented Apr 26, 2016 at 1:44
  • 1
    Oh my, this table-layout: fixed is a real gotcha! This answer should really be higher up. Commented Jul 18, 2021 at 20:35
19

Alternative way with just one class while keeping your styles in a CSS file, which even works in IE7:

<table class="mytable">
    <tr>
        <th>From</th>
        <th>Subject</th>
        <th>Date</th>
    </tr>
</table>
<style>
    .mytable td, .mytable th { width:15%; }
    .mytable td + td, .mytable th + th { width:70%; }
    .mytable td + td + td, .mytable th + th + th { width:15%; }
</style>

More recently, you can also use the nth-child() selector from CSS3 (IE9+), where you'd just put the nr. of the respective column into the parenthesis instead of stringing them together with the adjacent selector. Like this, for example:

<style>
    .mytable tr > *:nth-child(1) { width:15%; }
    .mytable tr > *:nth-child(2) { width:70%; }
    .mytable tr > *:nth-child(3) { width:15%; }
</style>
6
  • The proposed :nth-child solution is horrible in terms of performance. There is no valid reason to use it (especially with the universal selector) in this example where there are only three elements (th or col) to style. Additionally, you only need to set width to the th in the first row. The .mytable td in the first example is redundant.
    – tomasz86
    Commented Apr 25, 2016 at 16:29
  • 2
    "The proposed :nth-child solution is horrible in terms of performance." - citation needed.
    – DanMan
    Commented Apr 25, 2016 at 21:10
  • This should be enough: Efficiently Rendering CSS. With your use of the universal selector the browser will first check ALL elements whether they are nth child of another element, then if their direct parent is tr and then whether they belong to .mytable. If you really want to use "nth" then something like this will probably be much better: .mytable th:nth-of-type(1) {width: 15%}; .mytable th:nth-of-type(2) {width: 70%};. There is also no need to specify the third column width in this case.
    – tomasz86
    Commented Apr 26, 2016 at 1:27
  • Personally I would use classes or just .mytable th+th{width: 70%}.mytable th+th+th{width:15%}. The "nth" selectors themselves may be very useful but in this particular case (a tiny table with only 3 columns) are not really needed. When using table-layout: fixed you can even do just this: table{table-layout:fixed}th:first-child+th{width:70%}.
    – tomasz86
    Commented Apr 26, 2016 at 2:23
  • I'm aware of that. But those articles are from years back, and there are bigger problems today that CSS selectors, like huge amounts of images and JS code.
    – DanMan
    Commented Apr 26, 2016 at 19:58
15

These are my two suggestions.

  1. Using classes. There is no need to specify width of the two other columns as they will be set to 15% each automatically by the browser.

        table { table-layout: fixed; }
        .subject { width: 70%; }
        <table>
          <tr>
            <th>From</th>
            <th class="subject">Subject</th>
            <th>Date</th>
          </tr>
        </table>

  2. Without using classes. Three different methods but the result is identical.

    a)

        table { table-layout: fixed; }
        th+th { width: 70%; }
        th+th+th { width: 15%; }
        <table>
          <tr>
            <th>From</th>
            <th>Subject</th>
            <th>Date</th>
          </tr>
        </table>

    b)

        table { table-layout: fixed; }
        th:nth-of-type(2) { width: 70%; }
        <table>
          <tr>
            <th>From</th>
            <th>Subject</th>
            <th>Date</th>
          </tr>
        </table>

    c) This one is my favourite. Same as b) but with better browser support.

        table { table-layout: fixed; }
        th:first-child+th { width: 70%; }
        <table>
          <tr>
            <th>From</th>
            <th>Subject</th>
            <th>Date</th>
          </tr>
        </table>

9

Add colgroup after your table tag. Define width and number of columns here, and add the tbody tag. Put your tr inside of tbody.

<table>
    <colgroup>
       <col span="1" style="width: 30%;">
       <col span="1" style="width: 70%;">
    </colgroup>
    
    
    <tbody>
        <tr>
            <td>First column</td>
            <td>Second column</td>
        </tr>
    </tbody>
</table>
1
  • colgroup seems to only works when you set table-layout: "fixed" on the table using css. You also dont need the styles on the col. Afterwards, you specify the width as the colspan on the individual td cells eg <td colspan="3"></td>
    – Gilbert
    Commented May 27 at 21:33
5

Depending on your body (or the div which is wrapping your table) 'settings' you should be able to do this:

body {
  width: 98%;
}

table {
  width: 100%;
}


th {
  border: 1px solid black;
}


th.From, th.Date {
  width: 15%;
}

th.Date {
  width: 70%;
}


<table>
  <thead>
    <tr>
      <th class="From">From</th>
      <th class="Subject">Subject</th>
      <th class="Date">Date</th>
    </tr>
   </thead>
   <tbody>
     <tr>
       <td>Me</td>
       <td>Your question</td>
       <td>5/30/2009 2:41:40 AM UTC</td>
     </tr>
   </tbody>
</table>

Demo

5

Try this instead.

<table style="width: 100%">
    <tr>
        <th style="width: 20%">
           column 1
        </th>
        <th style="width: 40%">
           column 2
        </th>
        <th style="width: 40%">
           column 3
        </th>
    </tr>
    <tr>
        <td style="width: 20%">
           value 1
        </td>
        <td style="width: 40%">
           value 2
        </td>
        <td style="width: 40%">
           value 3
        </td>
    </tr>
</table>
5

    table { table-layout: fixed; }
    .subject { width: 70%; }
    <table>
      <tr>
        <th>From</th>
        <th class="subject">Subject</th>
        <th>Date</th>
      </tr>
    </table>

4

Here's another minimal way to do it in CSS that works even in older browsers that do not support :nth-child and the like selectors: http://jsfiddle.net/3wZWt/.

HTML:

<table>
    <tr>
        <th>From</th>
        <th>Subject</th>
        <th>Date</th>
    </tr>
    <tr>
        <td>Dmitriy</td>
        <td>Learning CSS</td>
        <td>7/5/2014</td>
    </tr>
</table>

CSS:

table {
    border-collapse: collapse;
    width: 100%;
}

tr > * {
    border: 1px solid #000;
}

tr > th + th {
    width: 70%;
}

tr > th + th + th {
    width: 15%;
}
4
<table>
  <col width="130">
  <col width="80">
  <tr>
    <th>Month</th>
    <th>Savings</th>
  </tr>
  <tr>
    <td>January</td>
    <td>$100</td>
  </tr>
  <tr>
    <td>February</td>
    <td>$80</td>
  </tr>
</table>

Demo

1
  • 8
    The col width attribute is not supported in HTML5.
    – Rune
    Commented Jul 22, 2015 at 10:51
3

Don't use the border attribute, use CSS for all your styling needs.

<table style="border:1px; width:100%;">
    <tr>
            <th style="width:15%;">From</th>
            <th style="width:70%;">Subject</th>
            <th style="width:15%;">Date</th>
    </tr>
... rest of the table code...
</table>

But embedding CSS like that is poor practice - one should use CSS classes instead, and put the CSS rules in an external CSS file.

1
  • 1
    I would suspect that the example code the OP and helpful stackoverflowians posted was for legibility and simplicity's sake, by no means an encouragement for inline styles.
    – Tass
    Commented Jul 20, 2011 at 20:58
-3
style="column-width:300px;white-space: normal;"
1
  • Hi - welcome to Stack Overflow. In general, answers with text (instead of just code) and some explanation are viewed as better than just code-only answers. Since this question is older and has a lot of other answers, they may help guide you in future answers.
    – jwheron
    Commented Sep 20, 2018 at 20:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.