136

I have the following code:

.table {
  display: table;
}

.row {
  display: table-row;
}

.cell {
  display: table-cell;
}

.colspan2 {
  /* What to do here? */
}
<div class="table">
  <div class="row">
    <div class="cell">Cell</div>
    <div class="cell">Cell</div>
  </div>
  <div class="row">
    <div class="cell colspan2">Cell</div>
  </div>
</div>

Pretty straightforward. How do I add a colspan (or the equivalent of colspan) for elements with display: table-cell?

Bumhan Yu
  • 2,078
  • 1
  • 10
  • 20
Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
  • 7
    Can't you just use a table? It would be a lot easier. Plus if this is tabular data it would be more semantic too. – punkrockbuddyholly Feb 14 '12 at 13:27
  • @thirtydot it probably can, it would just be a pain and unnecessary. Grid systems like 960 basically achieve this but for an entire page layout. – punkrockbuddyholly Feb 14 '12 at 14:03
  • @MrMisterMan: I'm not sure what you're saying. 960.gs doesn't use `display: table-cell`. – thirtydot Feb 14 '12 at 14:06
  • @thirtydot sorry, I forgot the specific question the OP had asked. You're right, you can't add a colspan through CSS. I was pointing out that you *can* make div's behave like rows and columns and that includes cells spanning multiple columns. – punkrockbuddyholly Feb 14 '12 at 14:24
  • Use a simulated table as you do for your first level of organisation, wich will give you the ability to create a sticky footer for example. for your colspan emulation, you can created a nested table in your unique cell, wich will have a single row and as many cell you need, or use simple floating div. – Bernard Dusablon Apr 02 '13 at 15:28
  • look [here](http://stackoverflow.com/q/4746061/1429387) for div table colspan. – naXa stands with Ukraine Oct 18 '16 at 16:01

15 Answers15

56

As far as I know, the lack of colspan/rowspan is just one of the limitations of display:table. See this post:

http://www.onenaught.com/posts/201/use-css-displaytable-for-layout

Russell Zahniser
  • 16,188
  • 39
  • 30
30

Since OP does not explicitly rule that solution must be pure CSS, I'll be stubborn and throw in my workaround I figured out today, especially since it's much more elegant than having a table inside a table.

Example equals to <table> with two cells per row and two rows, where the cell in the second row is a td with colspan="2".

I have tested this with Iceweasel 20, Firefox 23 and IE 10.

div.table {
  display: table;
  width: 100px;
  background-color: lightblue;
  border-collapse: collapse;
  border: 1px solid red;
}

div.row {
  display: table-row;
}

div.cell {
  display: table-cell;
  border: 1px solid red;
}

div.colspan,
div.colspan+div.cell {
  border: 0;
}

div.colspan>div {
  width: 1px;
}

div.colspan>div>div {
  position: relative;
  width: 99px;
  overflow: hidden;
}
<div class="table">
    <div class="row">
        <div class="cell">cell 1</div>
        <div class="cell">cell 2</div>
    </div>
    <div class="row">
        <div class="cell colspan">
            <div><div>
                cell 3
            </div></div>
        </div>
        <div class="cell"></div>
    </div>
</div>

Live action (demo) here.

EDIT: I finetuned the code to be more printer-friendly, as they leave background-colors out by default. I also created rowspan-demo, inspired by late answer here.

JustCarty
  • 3,839
  • 5
  • 31
  • 51
F-3000
  • 935
  • 13
  • 13
  • I am looking for a similar solution. But instead, I have 5 cells on top row. On the bottom row, I need 1 cell same size as top row. Then one cell having colspan=2 and another cell having colspan=2 making it total of 5 cells in the bottom row as well. Here's the jsfiddle problem based on your solution. Any thoughts? https://jsfiddle.net/7wdza4ye/1/ – Varun Verma Aug 16 '17 at 16:40
  • 1
    @VarunVerma, you must add empty cell between cells 7 and 8. Just adding `
    ` works (at least with Firefox). With this design, you need to pad with empty cell(s). For example, if you had it so that cell 7 was colspan=3 and cell 8 was normal, then you'd need two empty cells between cells 7 and 8. Unless you'd design something else (margins? single customized div?). Also, width of 100px and 5 cells makes things tricky, because words stretches css-cells, overflow-settings doesn't seem to make difference. You also need to recalculate `width` for `div.colspan>div>div`.
    – F-3000 Aug 16 '17 at 21:55
  • it worked. Thanks. In fact, I did add an empty cell after cell 8 because the bottom border wasn't showing up. Here's the latest: https://jsfiddle.net/7wdza4ye/3/. Was sure how to get the border between cell 7 and 8. Any suggestions? Thanks for your help. – Varun Verma Aug 18 '17 at 18:28
  • 1
    @VarunVerma, with Chrome the outer border was incomplete without empty cell after 8, so it is required indeed. Simple way to add the border between cells 7 and 8 could be this: `div.colspan{border-left:1px solid red}`. It needs to be placed somewhere below rule that sets div.colspan borderless, or it'll be overruled. – F-3000 Aug 19 '17 at 15:08
  • Thanks @F-3000. That was helpful. For the rest, here's the latest link based on F-3000's solution: https://jsfiddle.net/7wdza4ye/4/ – Varun Verma Aug 21 '17 at 17:37
17

A simpler solution that works for me in Chrome 30 :

Colspan can be emulated by using display: table instead of display: table-row for the rows :

.table {
    display: block;
}
.row {
    display: table;
    width: 100%;
}
.cell {
    display: table-cell;
}
.row.colspan2 {/* You'll have to add the 'colspan2' class to the row, and remove the unused <div class=cell> inside it */
    display: block;
}

The only pitfall is that the cells of stacked rows won't align vertically, as they're from different tables.

Philippe97
  • 380
  • 4
  • 9
9

If you're looking for a straight CSS way to simulate a colspan, you could use display: table-caption.

.table {
  display: table;
}
.row {
  display: table-row;
}
.cell {
  display: table-cell;
  border: 1px solid #000;
}
.colspan2 {
  /* What to do here? */
  display: table-caption;
}
<div class="table">
    <div class="row">
        <div class="cell">Cell</div>
        <div class="cell">Cell</div>
    </div>
    <div class="row">
        <div class="cell colspan2">Cell</div>
    </div>
</div>
JustCarty
  • 3,839
  • 5
  • 31
  • 51
stacigh
  • 676
  • 1
  • 7
  • 13
  • That is amazing you rock! – Raj Kamal Sep 27 '17 at 16:00
  • 2
    Using display: table-caption will span all columns and place the row at the top of the table, just like a caption element in html table, so this doesn't really work. Only if you want to span all columns on the first or last row. – Michiel Jul 10 '18 at 12:45
7

Simply use a table.

table's are only frowned upon when being used for layout purposes.

This seems like tabular data (rows/columns of data). Therefore I would recommend using a table.

See my answer to this question for more information:

creating the same thing with divs as tables

Community
  • 1
  • 1
Curtis
  • 101,612
  • 66
  • 270
  • 352
  • 15
    The thing is, it's not for tabular data, so I don't want to use a table :) – Madara's Ghost Feb 14 '12 at 15:24
  • 16
    I don't get why CSSing everything to behave exactly like a table is somehow preferable to just using a table. Admittedly `tr`/`td` spam isn't the prettiest html but is that the only reason? Everyone says tables weren't "meant" to be used for formatting, but html itself wasn't "meant" to do half of the things we consider acceptable by today's standards, including web applications. – Slight Apr 04 '16 at 20:29
  • 4
    Nearly a year later, but -- Slight, I share your irritation with people avoiding tables for no reason other than "tables are out of style". However I'm running into a few responsive designs where it's useful to have a table not be a table, so it can be rearranged at lower widths. Learning I don't have colspan for divs is kinda disappointing. – spinn Feb 28 '17 at 16:35
  • I formatted my search bar and menu icons using table/tr/td. I discovered why I shouldn't do that when I started testing with screen readers. Android's TalkBack reads out the table, number of rows, columns, etc. as though it's a data table. BUT, then saw I can keep the table/tr/td if I use role="presentation" Noticed Gmail does that with its search bar formatting. – user984003 Jul 03 '23 at 20:42
5

Here's one way to span columns in CSS I used for my own situation.

https://jsfiddle.net/mb8npttu/

.table {
  display: table;
}

.row {
  display: table-row;
}

.cell {
  display: table-cell;
  border: 1px dotted red;
}

.colspan {
  max-width: 1px;
  overflow: visible;
}
<div class='table'>
  <div class='row'>
    <div class='cell colspan'>
      spanning
    </div>
    <div class='cell'></div>
    <div class='cell'></div>
  </div>

  <div class='row'>
    <div class='cell'>1</div>
    <div class='cell'>2</div>
    <div class='cell'>3</div>
  </div>
</div>
vsync
  • 118,978
  • 58
  • 307
  • 400
Tim
  • 85
  • 1
  • 8
  • 3
    I had to augment `.colspan` with `white-space: nowrap;` to get the result I wanted, but it worked great. – kshetline Jun 01 '18 at 02:41
2

There is a solution to make the colspan the widht of the entire table. You can not use this technique to colspan a part of the table.

Code:

* {
  box-sizing: border-box;
}

.table {
  display: table;
  position: relative;
}

.row {
  display: table-row;
}

.cell {
  display: table-cell;
  border: 1px solid red;
  padding: 5px;
  text-align: center;
}

.colspan {
  position: absolute;
  left: 0;
  width: 100%;
}

.dummycell {
  border-color: transparent;
}
<div class="table">
  <div class="row">
    <div class="cell">Cell</div>
    <div class="cell">Cell</div>
  </div>
  <div class="row">
    <div class="cell dummycell">&nbsp;</div>
    <div class="cell colspan">Cell</div>
  </div>
  <div class="row">
    <div class="cell">Cell</div>
    <div class="cell">Cell</div>
  </div>
</div>

Explanation:

We use position absolute on the colspan to make it the full width of the table. The table itself needs position relative. We make use of a dummycell to maintain the height of the rows, position absolute does not follow the flow of the document.

Of course you can also use flexbox and grid to tackle this problem these days.

vsync
  • 118,978
  • 58
  • 307
  • 400
J.T. Houtenbos
  • 956
  • 7
  • 17
1

CSS

.tablewrapper {
  position: relative;
}
.table {
  display: table;
  position: relative
}
.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;
}
.cell.colspan {
  position: absolute;
  left: 0;
  right: 0;
}

HTML

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

Code

bderevyaga
  • 31
  • 3
1

It can be done just with pure CSS and centering the text across the "fake" colspan.

The trick is to set the rows to position:relative, then to place "empty divs" in the row where you want to make the colspan (they must have height in order to work), set the cell where the content is in as display:grid, and finally, applying position:absolute to the element inside the cell (and center it as you may center any other absolute element).

 .table {
        display: table;
  }
  .row {
      display: table-row;
      position: relative;
  }
  .cell {
      display: table-cell;
      background-color: blue;
      color: white;
      height: 26px;
      padding: 0 8px;
  } 
  .colspan2 {
      display: grid;
  }
  .colspan2 p {
    position:absolute;
    left: 50%;
    transform:translateX(-50%);
    margin: 0;
  }
<div class="table">
    <div class="row">
        <div class="cell">Cell</div>
        <div class="cell">Cell</div>
    </div>
    <div class="row">
        <div class="cell colspan2"><p>Cell</p></div>
        <div class="cell"></div>
    </div>
</div>
Joe82
  • 1,357
  • 2
  • 24
  • 40
0

By using the appropriate div classes and CSS attributes, you can mimic the desired effects of the colspan and rowspan.

Here's the CSS

.table {
    display:table;
}

.row {
    display:table-row;
}

.cell {
    display:table-cell;
    padding: 5px;
    vertical-align: middle;
}

Here's the sample HTML

<div class="table">
    <div class="row">
        <div class="cell">
            <div class="table">
                <div class="row">
                    <div class="cell">X</div>
                    <div class="cell">Y</div>
                    <div class="cell">Z</div>
                </div>
                <div class="row">
                    <div class="cell">2</div>
                    <div class="cell">4</div>
                    <div class="cell">6</div>
                </div>
            </div>
        </div>
        <div class="cell">
            <div class="table">
                <div class="row">
                    <div class="cell">
                        <div class="table">
                            <div class="row">
                                <div class="cell">A</div>
                            </div>
                            <div class="row">
                                <div class="cell">B</div>
                            </div>
                        </div>
                    </div>
                    <div class="cell">
                        ROW SPAN
                    </div>    
                </div>
            </div>
        </div>
    </div>
</div>    

From what I'm seeing in both the questions, and most responses, is people seem to forget that in any given div that's acting as a "table-cell" you can insert another div that's acting like an embedded table, and start the process over.

***It's not glamorous, but it does work for those looking for this type of formatting and they want to avoid the TABLEs. If its for DATA LAYOUT, TABLEs do still work in HTML5.

Hopefully, this will help someone.

JRC
  • 29
  • 4
  • Firstly, HTML5 has full support for `` - it's just that people should **avoid** using it for _visual formatting_. Using it for displaying structured data is where it **should be used**, unless something else (like `
      `, as a mere example) fits better for the task. Secondly, dude, 4 tables. You bring interesting question onto table (rowspan), but your answer cries for using `
    ` instead. I gotta see how my solution works here...
– F-3000 Aug 25 '15 at 09:36
  • I'd edit my earlier comment, but timelimit hits in. As with my answer about colspan, rowspan can be accomplished with MUCH less hassle than with your... original approach. [See it yourself](http://atkkierratys.com/demot/csstablewithrowspan.htm). – F-3000 Aug 25 '15 at 11:29
  • Thanks for your feedback. I never said HTML5 didn't support tables. Many people are simply looking to avoid it. Sometimes, when writing a web-app (as opposed to just an advertisting-type page), you need more of a fixed layout for button and/or control placement. – JRC Sep 02 '15 at 20:38