JavaScript
Article
By Kevin Yank

Rowspans & Colspans in CSS Tables

By Kevin Yank

“…we’ve implemented every property in CSS 2.1 and are closing in on our goal of complete support for the CSS 2.1 specification by the time we release.”

If you were to guess who recently made that statement you’d be forgiven for thinking it came from the Opera, Safari, or Firefox team; they have always seemed to be the most standards-conscious browser vendors. In fact, this quote comes from Doug Stamper of Microsoft, regarding Internet Explorer 8.

It seems the very thing web designers have been asking for—mature support for CSS2.1 across all major browsers—is actually about to happen. Back in Tech Times #185, I wrote about what this would mean to web designers in Table-Based Layout Is The Next Big Thing. In short, I said that CSS tables would become the best tool for CSS page layout.

There were mixed reactions to that article, particularly on the point of row and column spans. HTML tables let you create cells that span multiple rows or columns, but CSS tables don’t provide that same freedom.

Well, in my research for an as yet unannounced, potentially controversial book on CSS, I’ve figured out how to simulate row and column spans in CSS tables. Rather than make you wait for the book, I thought I’d show you this useful technique right away!

--ADVERTISEMENT--

Nothing Up My Sleeve…

If you’ve had experience building layouts using HTML tables, you’ll be familiar with the use of the colspan and rowspan attributes of the td element. These attributes offer complex possibilities to a simple table, enabling cells to span columns and rows.

CSS tables lack any concept of row or column spanning, making it trickier to use one single layout structure than what might have been possible when using tables. However, similar layouts can be achieved by using nested CSS tables.

Of course, nested tables are not a perfect solution. When you want to match the dimensions of cells across nested tables, for example, things can get messy in a hurry, and the extra <div> tags really start to add up.

As it turns out, it’s also possible to simulate row and column spanning using absolute positioning of table cells, in many cases. In this example, we’ll make the second cell of the first row of a table span both rows of the table (as if it had a rowspan of 2). First, let’s take a look at the HTML code:

<div class="tablewrapper">
  <div class="table">
    <div class="row">
      <div class="cell">
        Top left
      </div>
      <div class="rowspanned cell">
        Center
      </div>
      <div class="cell">
        Top right
      </div>
    </div>
    <div class="row">
      <div class="cell">
        Bottom left
      </div>
      <div class="empty cell"></div>
      <div class="cell">
        Bottom right
      </div>
    </div>
  </div>
</div>

You’ll notice that we’ve wrapped our table div in an extra div with a class of "tablewrapper". This extra div is needed to provide a CSS positioning context—which we create by giving it relative positioning:

.tablewrapper {
  position: relative;
}

According to the CSS spec, we should be able to simply apply relative positioning to the table div, but current browsers don’t seem to support this.

Sleight of Hand and Absolute Positioning

Now, we can use absolute positioning to control the size and position of the div with class "rowspanned cell":

.cell.rowspanned {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100px;
}

With the top and bottom properties both set to zero, the cell will stretch to fill the full height of the table, simulating a row span. Depending on the needs of your layout, you could use different values for top and bottom, or even set the cell’s height directly to achieve other row-spanning layouts.

You also need to specify the width of the cell. Usually, the easiest way to do this is just to set its width property, but depending what you know of the dimensions of surrounding table cells, you could also do this by setting left and right.

Since the positioned cell doesn’t actually span multiple rows of the table, the table must still contain a corresponding cell in each of the other rows. These cells are simply empty placeholders, though; note the div with class "empty cell" in the HTML code above. The function of this cell is to hold open the space that will be occupied by the “spanned” cell, so we must ensure its width matches the width we specified for the "rowspanned cell":

.cell.empty {
  width: 100px;
}

And that’s all there is to it! To complete the style sheet for this example, we need only set the appropriate display property values, and add some borders so we can see what’s going on:

.tablewrapper {
  position: relative;
}
.table {
  display: table;
}
.row {
  display: table-row;
}
.cell {
  border: 1px solid red;
  display: table-cell;
}
.cell.empty
{
  border: none;
  width: 100px;
}
.cell.rowspanned {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100px;
}

In essence, by using absolute positioning we are telling the browser, “Let me handle the layout of this table cell—you take care of the rest.” Here’s what the results look like:

Try it for yourself. This example works in all major browsers except for Internet Explorer 7, and also works in the current IE8 Beta 2 release.

What do you think? Can you see yourself switching to CSS tables for layout as your Internet Explorer users make the move to IE8?

Recommended
Sponsors
The most important and interesting stories in tech. Straight to your inbox, daily. Get Versioning.
Login or Create Account to Comment
Login Create Account