Friday, March 4, 2011

Two HTML tables side by side, centered on the page

I have two tables on a page that I want to display side by side, and then center them within the page (actually within another div, but this is the simplest I could come up with):

<style>
  #outer { text-align: center; }
  #inner { text-align: left; margin: 0 auto; }
  .t { float: left; }
  table { border: 1px solid black; }
  #clearit { clear: left; }
</style>

<div id="outer">
  <p>Two tables, side by side, centered together within the page.</p>

  <div id="inner">
    <div class="t">
      <table>
        <tr><th>a</th><th>b</th></tr>
        <tr><td>1</td><td>2</td></tr>
        <tr><td>4</td><td>9</td></tr>
        <tr><td>16</td><td>25</td></tr>
      </table>
    </div>

    <div class="t">
      <table>
        <tr><th>a</th><th>b</th><th>c</th></tr>
        <tr><td>1</td><td>2</td><td>2</td></tr>
        <tr><td>3</td><td>5</td><td>15</td></tr>
        <tr><td>8</td><td>13</td><td>104</td></tr>
      </table>
    </div>

  </div>
  <div id="clearit">all done.</div>
</div>

I understand that it's something to do with the fact that the tables are floated, but I'm at a loss as to understand what I'm missing. There are many web pages that describe something like the technique I show here, but in any event it doesn't work; the tables cling stubbornly to the left hand margin.

From stackoverflow
  • Off the top of my head, you might try using the "margin: 0 auto" for #outer rather than #inner.

    I often add background-color to my DIVs to see how they're laying out on the view. That might be a good way to diagnose what's going onn here.

    dland : Tried auto everywhere, no joy. Tried the background-color trick too (actually I prefer border: 1px solid black, but I digress). The trouble is #inner spans the whole width, and the tables aren't covered by it, since they're floated...
  • The problem is that the DIV that should center your tables has no width defined. By default, DIVs are block elements and take up the entire width of their parent - in this case the entire document (propagating through the #outer DIV), so the automatic margin style has no effect.

    For this technique to work, you simply have to set the width of the div that has margin:auto to anything but "auto" or "inherit" (either a fixed pixel value or a percentage).

  • Give your inner div a width.

    EXAMPLE

    Change your CSS:

    <style>
    #outer { text-align: center; }
    #inner { text-align: left; margin: 0 auto; }
    .t { float: left; }
    table { border: 1px solid black; }
    #clearit { clear: left; }
    </style>
    

    To this:

    <style>
    #outer { text-align: center; }
    #inner { text-align: left; margin: 0 auto; width:500px }
    .t { float: left; }
    table { border: 1px solid black; }
    #clearit { clear: left; }
    </style>
    
    dland : Hmm, I see. The trouble is that the tables are generated dynamically. I can't tweak a pixel value to make things line up nicely.
    Andrew G. Johnson : If that is the case then you unfortunately can't do what you're asking to do.
  • The problem is that you need to give #inner a set width (anything but auto or inherit). The margin: 0 auto; trick only works if the inner element is narrower than its container element. Without being given a width, #inner is automatically expanding to the full width of #outer, which causes its contents to be flush left.

  • If it was me - I would do something like this:

    <style type="text/css" media="screen">
     table { border: 1px solid black;float:left;width:148px;}
     #table_container{width:300px;margin:0 auto;}
    </style>
    

    With the table like:

    <div id="table_container">
      <table>
        <tr>
          <th>a</th>
          <th>b</th>
        </tr>
        <tr>
          <td>1</td>
          <td>2</td>
        </tr>
        <tr>
          <td>4</td>
          <td>9</td>
        </tr>
        <tr>
          <td>16</td>
          <td>25</td>
        </tr>
      </table>
      <table>
        <tr>
          <th>a</th>
          <th>b</th>
        </tr>
        <tr>
          <td>1</td>
          <td>2</td>
        </tr>
        <tr>
          <td>4</td>
          <td>9</td>
        </tr>
        <tr>
          <td>16</td>
          <td>25</td>
        </tr>
      </table>
    </div>
    
    Shawn Simon : was going to post this, this is the way to go.
    Darko Z : agreed, this is the simplest solution. would have posted this but its already here :) +1
    Darko Z : if you cant set the width as mentioned in a comment below, set overflow:hidden on the container so that the container doesnt collapse.
  • <style>
    #outer { text-align: center; }
    #inner { width:500px; text-align: left; margin: 0 auto; }
    .t { float: left; width:240px; border: 1px solid black;}
    #clearit { clear: both; }
    </style>
    
  • Unfortunately, all of these solutions rely on specifying a fixed width. Since the tables are generated dynamically (statistical results pulled from a database), the width can not be known in advance.

    The desired result can be achieved by wrapping the two tables within another table:

    <table align="center"><tr><td>
    ... the two tables ...
    </td></tr></table>
    

    and the result is a perfectly centered pair of tables that responds fluidly to arbitrary widths and page (re)sizes (and the align="center" table attribute could be hoisted out into an outer div with margin autos).

    I conclude that there are some layouts that can only be achieved with tables.

    Tim K. : what I would do then dland would be to use something like jQuery to determine the width of the tables and then add the two totals together to determine the width needed for the container.
  • I realize this is an ancient question, but here goes anyway.

    The following will work in compliant browsers and IE8 in standards mode (i.e. with a doctype set).

    #inner {text-align:center;}
    .t {display:inline-block;}
    

    Unfortunately, there's really no way to tweak it to work in IE6. For IE7, adding a zoom:1 to the .t divs (via a conditional comment) might help, but I don't have IE7 available for testing at the moment.

    dland : +1 for posting to an old question! In the meantime, I also found a solution using display: table-cell, which as you can imagine fails miserably on IE6. I finally threw in the towel and added some evil IE6 comment hackery to emit , ,
    elements for IE6. Seems to work well enough.
    Martha : AFAIK, no version of IE supports display:table-cell, which is why I went with inline-block. Btw, I just tested it, and I got the tables to go side-by-side in IE7 by adding ".t {display:inline;zoom:1;}" in a conditional comment.

    0 comments:

    Post a Comment