13

Is it possible to have a table with width 100% (so the table fits the screen size), where the first and the last column have a fixed width, and the columns between take the rest, both 50%.

Like:

+--------------------+--------------------------------------+--------------------------------------+------------+
| width:300px;       | with dynamic, equals next column     | width dynamic, equals prevous column | width:50px;|
+--------------------+--------------------------------------+--------------------------------------+------------+
+--------------------+--------------------------------------+--------------------------------------+------------+
+--------------------+--------------------------------------+--------------------------------------+------------+
+--------------------+--------------------------------------+--------------------------------------+------------+
3
  • have you tried? It might actually work. UPADTE: tried it myself and it doesn't work, the %columns make the pxcolumns smaller. Commented Jul 29, 2011 at 11:59
  • @thobens - Not with pure css - you will need a javascript that will convert your 300px to % value and than recalculate the width of the inner columns. Commented Jul 29, 2011 at 12:06
  • what I forgot to mention: the table contents of the two middle columns are dynamic. In the left column are buttons, where the onclick changes the content of the two columns in the middle. So, if I don't specify the width of the two middle columns, the browser changes the widths of these columns everytime the content changes. It seems that easwee's approach is appropriate, as the whole table is created by javascript. Commented Jul 29, 2011 at 12:17

7 Answers 7

25

Try this:

As you can see the two centre column remain equal sized, due to the table-layout:fixed, even when the content is of different length. Try adding more and less content to the two centre columns.

JSFiddle: http://jsfiddle.net/RtXSh/

CSS

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

td {
    border: 1px solid #333;
}

HTML

  <table>
    <tr>
      <td style="width:300px;">
        test
      </td>
      <td>
        test test tes test test
      </td>
      <td>
        test
      </td>
      <td style="width:50px;">
        test
      </td>
    </tr>
  </table>
Sign up to request clarification or add additional context in comments.

2 Comments

This works for me on my current project, except it no longer respects the min-width setting I have on my columns.
I'd say min-width doesn't mean anything on a table that has it's layout fixed. Frankly I'm just guessing but it seems logical: min-width is for columns that can size dynamically (they should not size wider than the min-width), a fixed table layout means that columns can no longer size, they are fixed. Hence min-width has no purpose on such column. I think.
13

Try using the pseudo element first-child and last-child

If I'm not mistaken the other columns will align equally by themselves. You might need to use the !important statement behind the first-child and last-child widths.

table{ table-layout: fixed; width: 100%; }
td { border: 1px solid black; }
td:first-child{ width: 100px; }
td:last-child{ width: 100px; }
<table>
    <tr>
      <td>100px</td>
      <td>some text</td>
      <td>some text</td>
      <td>100px</td>
    </tr>
</table>

However, as nurettin pointed out, if you use a thead and tbody section you have to style the header. Styling the td:first-child and td:last-child will not work.

table{ table-layout: fixed; width: 100%; }
td { border: 1px solid black; }
th:first-child{ width: 100px; }
th:last-child{ width: 100px; }
<table>
  <thead>
    <tr>
      <th>Column 1</th>
      <th>Column 2</th>
      <th>Column 3</th>
      <th>Column 4</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>100px</td>
      <td>some text</td>
      <td>some text</td>
      <td>100px</td>
    </tr>
  </tbody>
</table>

Comments

1

In my opinion, the simple, nice and easy way is that don't use the px and % together. If you are using table width 100%, then define width of first and last column in % as well. If you are interested in that, here is how you can do:

CSS:

.mytable {
    width:100%;
    border: 1px solid green;
}

.left{
    width:30%;
    border-right:1px dashed blue;
}

.mid1{
   width:30%;
   border-right:1px dashed blue;

}

.mid2{
  width:30%;
   border-right:1px dashed blue;

}

.right{
    width: 10%;
    border-left:1px dashed blue;
}

HTML:

<table class="mytable">
    <tr>
        <td class="left">Left Column, 30%</td>
        <td class="mid1">Mid 1, 30% </td>
        <td class="mid2">Mid 2, 30% </td>
        <td class="right">Right, 10%</td>
    </tr>
</table>

1 Comment

The problem here is, there are some design guidelines that tell me that the first column must be 300px... so there's not much I can do about it...
1

This can be handled by adding the style table-layout:fixed to the table element, and simply not specifying any width value for the columns you wish to evenly divide the width remaining after the fixed columns have been accounted for.

Further, using combinations of <colgroup> can provide robust variable-width scenarios.

I've created an example at JSFiddle: https://jsfiddle.net/3bgsfnuL/1/

<div style="position:relative; height:500px; width:100%;">
<table style="height:100%; width:100%; table-layout:fixed; text-align:center; border-collapse:collapse;">
  <colgroup colspan="1" style="width:200px"></colgroup>
  <colgroup colspan="3">
    <col/>
    <col style="width:30px"/>
    <col/>
  </colgroup>
  <colgroup colspan="1" style="width:200px"></colgroup>
  <tbody>
    <tr>
      <td style="background-color:silver;">left fixed</td>
      <td style="border-right:1px solid black;">col 1</td>
      <td style="background-color:red; color:white; border:1px solid black;">col 2</td>
      <td style="border-left:1px solid black;">col 3</td>
      <td style="background-color:silver;">right fixed</td>
    </tr>
  </tbody>
</table>
</div>

Comments

1

Nobody mentioned this one here <th> trick:

table{ table-layout: fixed; width: 100%; }
th:first-child{ width: 300px; }

<table>
  <thead>
    <tr>
      <th>yourfirst300pxcolumn</th>
      <th>fixedwidth</th>
      <th>fixedwidth also</th>
    </tr>
  </thead>
  <tbody>
    <tr><td>300</td><td>something</td><td>something else</td></tr>
  </tbody>
</table>

6 Comments

@GillesLesire I don't see "th" anywhere in your post.
so how exactly do you expect th:first-child to style any different from td:first-child? same result, same length, same complexity
@GillesLesire You are wrong. My Approach: jsfiddle.net/w1aLz2x8 your suggestion: jsfiddle.net/rto3vpyd/1 You can delete your claims (all of them are false) and I will delete my responses.
You mean jsfiddle.net/6py3e2Lh which was my answer, the person asking the question didn't say anything about using a thead and tbody. So in that case you have to assume it won't have one and simply style the tds. It works just fine without the tbody part. However interesting point that td:first-child doesn't work when using a thead.
@GillesLesire The original question drew an ASCII table. That means any html table structure can be induced from this. You can't deduce that he will not use th segments from that table. Neither can you assume that he will cut corners in order to avoid proper table layout structure. And neither can you claim to have responded with my exact same response. And neither can you say our approaches result in the same layout.
|
1

Note that in HTML5/CSS3, you can use grid layout to have more control over your tables. It's not that useful for this specific example, with pixel widths, where you can use table-layout:fixed as in Bazzz's answer, but it is useful if you want to use something like min-content.

The following works out of the box on Chrome and Firefox, but not in Safari:

table {
    width: 100%;
    display: grid;
    grid-template-columns: 300px 1fr 1fr 50px;

    /* Or, more usefully: */
    /* grid-template-columns: min-content 1fr 1fr min-content; */
}

td {
    display: block;
}

/* ignore <tr> when laying out the grid; just lay out the cells */
tr {
    display: contents;
}

/* browsers can inject <tbody> into the DOM even if it's not in the HTML */
tbody {
    display: contents;
}

screenshot

(Note though that the table border-collapse property doesn't work in this layout, so you may have to fiddle with CSS pseudo-classes like :last-child in order to get your borders to behave the way you want.)

In Safari this doesn't work -- the rows don't break properly. (Although it does work if you use nested <div> elements instead of a <table> and apply similar styles.) However, a simpler layout with just one dynamic 1fr column does work in Safari:

table {
  display: grid;
  grid-template-columns: 300px 1fr 50px;
}

tbody {
  display: contents;
}

tr {
  display: contents;
}

td {
  border: 1px solid #c0c0c0;
}

enter image description here

Comments

0

What about using jQuery for this and calling javascript function once your table is created or some other event (like click) happens?

See here (I created jsfiddle playground for this)

What it does is that it checks the width of fixed elements (width of the whole table, first and last cell). Then it calculates and assigns the width for the rest of the cells which should have the remaining width divided between them (based on how many there are and how much space is left). Of course this is just quick example of possible solution. It needs polishing (checking null objects, if remaining width is greater than 0, ...)

3 Comments

This is about the exact solution easwee suggested, i was implementing something similar. Allthough this is what i was looking for, thanks
Strange, a JS answer is accepted in a question with only HTML and CSS tags. But if it suits your needs, fair enough I guess.... My JSFiddle does the same thing with no JS though.
The reason why this is accepted is that the table is built using JS (and jQuery) and therefore I did not have to add extra JS support. I tried with table-layout:fixed; but it caused the columns to ignore the width of 300px and make all columns equal size (don't know why...). And I tagged it only with HTML and CSS because I hoped that it works w/o JS...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.