292

I'm trying to construct a layout similar to the following:

+---+---+---+
|   |   |   |
+---+---+---+
|           |
+-----------+

where the bottom is filling the space of the upper row.

If this were an actual table, I could easily accomplish this with <td colspan="3">, but as I'm simply creating a table-like layout, I cannot use <table> tags. Is this possible using CSS?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Tower
  • 98,741
  • 129
  • 357
  • 507
  • 11
    The best solution really depends on what is going into the table. If it's data (something that belongs in a table) then use a table. If you are using a table to control the layout of the page, then one of the HTML+CSS solutions below is better. – mwcz Mar 08 '10 at 19:31
  • Add markup for both cases, then show only one at a time using a Media query CSS class. – DigitalDesignDj May 12 '14 at 23:52
  • 2
    Forget about CSS. If you display tabular data, you would certainly know on how many columns it would span. Use the `colspan` attribute – Tihomir Mitkov Mar 11 '15 at 09:49
  • I would do this by bootstrap or customized grid from bootstrap – Arun Prasad E S Jul 15 '16 at 10:21
  • If you're using CSS3, you can use columnSpan. Unlike , you don't have the option to set the number of columns, but you can span all columns. https://www.w3schools.com/cssref/css3_pr_column-span.asp – MistyDawn Nov 22 '17 at 00:00
  • @MistyDawn -- The question is clearly about tables; your answer is not. The "column-span" you referenced has nothing to do with tables; it acts upon flowing text. The name "column-span" is reminiscent of the "colspan" attribute of HTML table's element, but the two concepts are very different. – IAM_AL_X Jun 23 '19 at 09:20
  • @IAM_AL_X -- The question isn't about tables; the asker explicitly states that using an HTML table is not an option and that they are "creating a table-like layout". CSS Grid is a good option as it is widely supported and utilizes native CSS instead of additional frameworks. If you can utilize Bootstrap, it makes this very simple by using the available table classes on
    elements.
    – MistyDawn Aug 15 '19 at 17:41
  • @MistyDawn -- Same problem. Not only is the "column-span" attribute inapplicable to the html element , but it is also inapplicable to
    , and it's inapplicable to CSS Grid. It is not intended for any "table-like layout". The "column-span" attribute applies to **flowing text** formatted with the CSS attribute "columns". Flowing text has blocks, but no rows; where-as "table-like" implies rows. The simple shape requested by the OP can be solved with "columns", but only If the OP abandons the notion of "table-like" and accepts blocks instead of rows.
    – IAM_AL_X Aug 19 '19 at 18:16

16 Answers16

430

There's no simple, elegant CSS analog for colspan.

Searches on this very issue will return a variety of solutions that include a bevy of alternatives, including absolute positioning, sizing, along with a similar variety of browser- and circumstance-specific caveats. Read, and make the best informed decision you can based on what you find.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
David
  • 4,452
  • 1
  • 15
  • 2
  • 13
    Tables are structural elements and just because using colspan changes its appearance does not mean it's not. CSS is used to style elements and not change the structure. The W3C discusses table structure here: http://www.w3.org/TR/html401/struct/tables.html#h-11.2 – Rob Apr 05 '10 at 16:40
  • 93
    Rob, understand your position, but look in the W3C recommendations - specifically pertaining to the entire table paradigm - and you'll find that part of their consideration was, most certainly, the *presentation* of tables. This idea that tables were purely conceived as structure is a contemporary fiction I think we'd all be better served to stop spreading. The point is we need to stop being dogmatic about tables. It would be wrong for me to say they're *always* presentation, and it is just as wrong for you to say they're *always* structure. Reality is simply not that cut-and-dried. – David Apr 05 '10 at 17:54
  • 4
    Looks like your answer *is* the popular answer. :) I'm happy to learn that the anti-table dogma (which I have bought into) is too strict. I do stand by my answer only insofar as I still think `colspan` is the right tool for the job. My answer was 75% right, and yours is 100% right. You should come back to SO. – mwcz Jan 17 '12 at 04:59
  • 81
    After 2 years, I googled this and wanted to vote up the author but it said "can't vote for your own post" and I realized it was me, lol. I decided to change the accepted solution to this one since I feel it has better information. – Tower Feb 29 '12 at 13:06
  • 2
    I think the deciding factor (for me at least) in the presentation vs structure argument is that by offering the "presentation" aspects of a "structural" element, the W3C is admitting (so to speak) that there are use-cases for an element to look like another element. And it's not really fair to extend this ability and then hit the brakes on col and row span on the grounds that this is a "structural" attribute, not stylistic. On the other side of the coin, I do think offering col and row span via CSS also opens the door for its use on actual table elements, which would be inappropriate. – Anthony Mar 24 '12 at 12:34
  • 15
    This is a mini-essay about some other (unspecified) answer, not an answer to the question asked. – Jukka K. Korpela Jun 29 '14 at 10:31
  • 1
    @Tower this answer is a dissertation, it doesn't answer your question and shouldn't be accepted. – fmsf Jun 08 '15 at 09:19
  • The truth is that HTML5 overall has failed about semantics. Because of CSS, mostly. I still do many div-subcontainers to reposition things other way. – Namek Aug 13 '15 at 13:43
  • 3
    The last two sentences of your first paragraph should be carved into the fabric of the internet. – Undistraction Dec 17 '15 at 13:02
  • 2
    For some reason it's difficult to find in stackoverflow an honest, objective, not ideological answer when the discussion is about using tables for layout purposes. This is one of the few honest answers, thanks David. It seems that people think in terms of dogma, forgetting that programmers have always used "hacks" and taken advantage of tools to solve problems different from the ones the tools were designed for. When there is no big side effects, I call this attitude creativity. – Eugenio Jun 11 '16 at 18:42
  • It's a shame that the relevant answer is half a sentence buried in the middle paragraph and surrounded by a massive rant. – Quentin Feb 16 '17 at 11:05
  • @Tower googling my own questions is all my life :( – Filip Bartuzi Jul 08 '18 at 12:20
  • This is really not an answer. – Steve Bennett Mar 30 '20 at 02:03
  • "There's no simple, elegant CSS analog for colspan." There is now! CSS Grid layout. See my answer. – Toby 1 Kenobi Jun 01 '20 at 08:54
62

There is no colspan in css as far as I know, but there will be column-span for multi column layout in the near future, but since it is only a draft in CSS3, you can check it in here. Anyway you can do a workaround using div and span with table-like display like this.

This would be the HTML:

<div class="table">
  <div class="row">
    <span class="cell red first"></span>
    <span class="cell blue fill"></span>
    <span class="cell green last"></span>
  </div>
</div>
<div class="table">
  <div class="row">
    <span class="cell black"></span>
  </div>
</div>

And this would be the css:

  /* this is to reproduce table-like structure
     for the sake of table-less layout. */
  .table { display:table; table-layout:fixed; width:100px; }
  .row { display:table-row; height:10px; }
  .cell { display:table-cell; }

  /* this is where the colspan tricks works. */
  span { width:100%; }

  /* below is for visual recognition test purposes only. */
  .red { background:red; }
  .blue { background:blue; }
  .green { background:green; }
  .black { background:black; }

  /* this is the benefit of using table display, it is able 
     to set the width of it's child object to fill the rest of 
     the parent width as in table */
  .first { width: 20px; }
  .last { width: 30px; }
  .fill { width: 100%; }

The only reason to use this trick is to gain the benefit of table-layout behaviour, I use it alot if only setting div and span width to certain percentage didn't fullfil our design requirement.

But if you don't need to benefit from the table-layout behaviour, then durilai's answer would suit you enough.

Community
  • 1
  • 1
O.O
  • 7,179
  • 1
  • 34
  • 32
  • 4
    Yup, but a little fix: instead of `.span { ...` it should be `span { ...`. – Slavik Meltser Dec 13 '12 at 14:12
  • 2
    Using `div` tags to display tabular data is as bad as using `table`s to control page layout – Tihomir Mitkov Mar 11 '15 at 09:43
  • 3
    @TichomirMitkov depends whether or not you're using responsive design to change the layout - in which case sometimes this can work quite well. – Simon_Weaver Apr 13 '16 at 02:00
  • 7
    This does not really answer the question since you essentially have two tables after each other in the example you gave. (I.e.two divs with the class "table") – Winter Aug 02 '16 at 14:42
26

Another suggestion is using flexbox instead of tables altogether. This is a "modern browser" thing of course, but come on, it's 2016 ;)

At least this might be an alternative solution for those looking for an answer to this nowadays, since the original post was from 2010.

Here's a great guide: https://css-tricks.com/snippets/css/a-guide-to-flexbox/

.table {
  border: 1px solid red;
  padding: 2px;
  max-width: 300px;
  display: flex;
  flex-flow: row wrap;
}
.table-cell {
  border: 1px solid blue;
  flex: 1 30%;
}
.colspan-3 {
  border: 1px solid green;
  flex: 1 100%;
}
<div class="table">
  <div class="table-cell">
    row 1 - cell 1
  </div>
  <div class="table-cell">
    row 1 - cell 2
  </div>
  <div class="table-cell">
    row 1 - cell 3
  </div>
  <div class="table-cell colspan-3">
    row 2 - cell 1 (spans 3 columns)
  </div>
</div>
Winter
  • 2,407
  • 1
  • 19
  • 28
  • 3
    I know this is old, but searches on 'colspan' lead here. In 2021, this is the only answer that fully answers the OP question and has widespread browser support. – Aaron Newman May 27 '21 at 23:07
  • Except that this uses flex. There may be cases where you need cells of multiple rows to align based on the content of any of the cells, which flex doesn't do, and tables do. So not sure about fully answering the OP. – Webber May 14 '23 at 17:44
8
<div style="width: 100%;">
    <div style="float: left; width: 33%;">Row 1 - Cell 1</div>
    <div style="float: left; width: 34%;">Row 1 - Cell 2</div>
    <div style="float: left; width: 33%;">Row 1 - Cell 3</div>
</div>
<div style="clear: left; width: 100%;">
Row 2 - Cell 1
</div>
Dustin Laine
  • 37,935
  • 10
  • 86
  • 125
7

To provide an up-to-date answer: The best way to do this today is to use css grid layout like this:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: auto;
  grid-template-areas: 
    "top-left top-middle top-right"
    "bottom bottom bottom"
}

.item-a {
  grid-area: top-left;
}
.item-b {
  grid-area: top-middle;
}
.item-c {
  grid-area: top-right;
}
.item-d {
  grid-area: bottom;
}

and the HTML

<div class="container">
  <div class="item-a">1</div>
  <div class="item-b">2</div>
  <div class="item-c">3</div>
  <div class="item-d">123</div>
</div>
Toby 1 Kenobi
  • 4,717
  • 2
  • 29
  • 43
6

That isn't part of the purview of CSS. colspan describes the structure of the page's content, or gives some meaning to the data in the table, which is HTML's job.

mwcz
  • 8,949
  • 10
  • 42
  • 63
  • 1
    OP explicitely mentions "creating a table-like *layout*", without structural meaning. Isn't it the very purpose of CSS tables ? There is no objective reason to treat colspan property differently than the whole table, if there is a design-only CSS table element, why not a design-only CSS colspan property… – Skippy le Grand Gourou Apr 25 '16 at 16:43
  • 2
    Check out the top-voted answer to this question. Your sentiment is discussed there already and I'm inclined to agree with it. My opinion on the issue has definitely shifted in the five years since I wrote this answer. – mwcz Apr 25 '16 at 17:33
4

I've had some success, although it relies on a few properties to work:

table-layout: fixed border-collapse: separate

and cell 'widths' that divide/span easily, i.e. 4 x cells of 25% width:

.div-table-cell,
* {
  box-sizing: border-box;
}

.div-table {
  display: table;
  border: solid 1px #ccc;
  border-left: none;
  border-bottom: none;
  table-layout: fixed;
  margin: 10px auto;
  width: 50%;
  border-collapse: separate;
  background: #eee;
}

.div-table-row {
  display: table-row;
}

.div-table-cell {
  display: table-cell;
  padding: 15px;
  border-left: solid 1px #ccc;
  border-bottom: solid 1px #ccc;
  text-align: center;
  background: #ddd;
}

.colspan-3 {
  width: 300%;
  display: table;
  background: #eee;
}

.row-1 .div-table-cell:before {
  content: "row 1: ";
}

.row-2 .div-table-cell:before {
  content: "row 2: ";
}

.row-3 .div-table-cell:before {
  content: "row 3: ";
  font-weight: bold;
}

.div-table-row-at-the-top {
  display: table-header-group;
}
<div class="div-table">

  <div class="div-table-row row-1">

    <div class="div-table-cell">Cell 1</div>
    <div class="div-table-cell">Cell 2</div>
    <div class="div-table-cell">Cell 3</div>

  </div>

  <div class="div-table-row row-2">

    <div class="div-table-cell colspan-3">
      Cor blimey he's only gone and done it.
    </div>

  </div>

  <div class="div-table-row row-3">

    <div class="div-table-cell">Cell 1</div>
    <div class="div-table-cell">Cell 2</div>
    <div class="div-table-cell">Cell 3</div>

  </div>

</div>

https://jsfiddle.net/sfjw26rb/2/

Also, applying display:table-header-group or table-footer-group is a handy way of jumping 'row' elements to the top/bottom of the 'table'.

user3464561
  • 101
  • 7
3

You could trying using a grid system like http://960.gs/

Your code would be something like this, assuming you're using a "12 column" layout:

<div class="container_12">
<div class="grid_4">1</div><div class="grid_4">2</div><div class="grid_4">3</div>
<div class="clear"></div>
<div class="grid_12">123</div>
</div>
Jeff
  • 4,751
  • 5
  • 31
  • 35
2

Try adding display: table-cell; width: 1%; to your table cell element.

.table-cell {
  display: table-cell;
  width: 1%;
  padding: 4px;
  border: 1px solid #efefef;
}
<div class="table">
  <div class="table-cell">one</div>
  <div class="table-cell">two</div>
  <div class="table-cell">three</div>
  <div class="table-cell">four</div>
</div>
<div class="table">
  <div class="table-cell">one</div>
  <div class="table-cell">two</div>
  <div class="table-cell">three</div>
  <div class="table-cell">four</div>
</div>
<div class="table">
  <div class="table-cell">one</div>
</div>
Ismail Farooq
  • 6,309
  • 1
  • 27
  • 47
  • how is that going to help? The fundamental concept of a table is that every row has identical cells. If one of the rows has a cell that successfully implements "width:1%", then all the rows will have that column as "width:1%". The point of "colspan" is to take 2 (or more) of the fixed width columns and combine them to get a combined width. – IAM_AL_X Jun 23 '19 at 09:26
  • Can you explain this, please? – Eliezer Berlin Aug 11 '20 at 13:18
  • The OP question said without table tags, table css is pretty much the same thing. there is no reason to do this vs. just creating a table. – Aaron Newman May 27 '21 at 23:06
1

The CSS properties "column-count", "column-gap", and "column-span" can do this in a way that keeps all the columns of the pseudo-table inside the same wrapper (HTML stays nice and neat).

The only caveats are that you can only define 1 column or all columns, and column-span doesn't yet work in Firefox, so some additional CSS is necessary to ensure it will displays correctly. https://www.w3schools.com/css/css3_multiple_columns.asp

.split-me {
  -webkit-column-count: 3;
  -webkit-column-gap: 0;
  -moz-column-count: 3;
  -moz-column-gap: 0;
  column-count: 3;
  column-gap: 0;
}

.cols {
  /* column-span is 1 by default */
  column-span: 1;
}

div.three-span {
  column-span: all !important;
}

/* alternate style for column-span in Firefox */
@-moz-document url-prefix(){
  .three-span {
    position: absolute;
    left: 8px;
    right: 8px;
    top: auto;
    width: auto;
  }
}


    
<p>The column width stays fully dynamic, just like flex-box, evenly scaling on resize.</p>

<div class='split-me'>
  <div class='col-1 cols'>Text inside Column 1 div.</div>
  <div class='col-2 cols'>Text inside Column 2 div.</div>
  <div class='col-3 cols'>Text inside Column 3 div.</div>
  <div class='three-span'>Text div spanning 3 columns.</div>
</div>



  <style>
/* Non-Essential Visual Styles */

html * { font-size: 12pt; font-family: Arial; text-align: center; }
.split-me>* { padding: 5px; } 
.cols { border: 2px dashed black; border-left: none; }
.col-1 { background-color: #ddffff; border-left: 2px dashed black; }
.col-2 { background-color: #ffddff; }
.col-3 { background-color: #ffffdd; }
.three-span {
  border: 2px dashed black; border-top: none;
  text-align: center; background-color: #ddffdd;
}
  </style>
MistyDawn
  • 856
  • 8
  • 9
0

if you use div and span it will occupy more code size when the datagrid-table row are more in volume. This below code is checked in all browsers

HTML:

<div id="gridheading">
<h4>Sl.No</h4><h4 class="big">Name</h4><h4>Location</h4><h4>column</h4><h4>column</h4><h4>column</h4><h4>Amount(Rs)</h4><h4>View</h4><h4>Edit</h4><h4>Delete</h4> 
</div>
<div class="data"> 
<h4>01</h4><h4 class="big">test</h4><h4>TVM</h4><h4>A</h4><h4>I</h4><h4>4575</h4><h4>4575</h4></div>
<div class="data"> 
<h4>01</h4><h4 class="big">test</h4><h4>TVM</h4><h4>A</h4><h4>I</h4><h4>4575</h4><h4>4575</h4></div>

CSS:

#gridheading {
    background: #ccc;
    border-bottom: 1px dotted #BBBBBB;
    font-size: 12px;
    line-height: 30px;
    text-transform: capitalize;
}
.data {
    border-bottom: 1px dotted #BBBBBB;
    display: block;
    font-weight: normal;
    line-height: 20px;
    text-align: left;
    word-wrap: break-word;
}
 h4 {
    border-right: thin dotted #000000;
    display: table-cell;
    margin-right: 100px;
    text-align: center;
    width: 100px;
    word-wrap: break-word;
}
.data .big {
    margin-right: 150px;
    width: 200px;
}
0

If you come here because you have to turn on or off the colspan attribute (say for a mobile layout):

Duplicate the <td>s and only show the ones with the desired colspan:

table.colspan--on td.single {
  display: none;
}

table.colspan--off td.both {
  display: none;
}
<!-- simple table -->
<table class="colspan--on">
  <thead>
    <th>col 1</th>
    <th>col 2</th>
  </thead>
  <tbody>
    <tr>
      <!-- normal row -->
      <td>a</td>
      <td>b</td>
    </tr>
    <tr>
      <!-- the <td> spanning both columns -->
      <td class="both" colspan="2">both</td>

      <!-- the two single-column <td>s -->
      <td class="single">A</td>
      <td class="single">B</td>
    </tr>
    <tr>
      <!-- normal row -->
      <td>a</td>
      <td>b</td>
    </tr>
  </tbody>
</table>
<!--
that's all
-->

 

<!--
stuff only needed for making this interactive example looking good:
-->
<br><br>
<button onclick="toggle()">Toggle colspan</button>
<script>/*toggle classes*/var tableClasses = document.querySelector('table').classList;
function toggle() {
  tableClasses.toggle('colspan--on');
  tableClasses.toggle('colspan--off');
}
</script>
<style>/* some not-needed styles to make this example more appealing */
td {text-align: center;}
table, td, th {border-collapse: collapse; border: 1px solid black;}</style>
luckydonald
  • 5,976
  • 4
  • 38
  • 58
0

I came here because currently the WordPress table block doesn't support the colspan parameter and i thought i will replace it using CSS. This was my solution, assuming that the columns are the same width:

table {
  width: 100%;
}

table td {
  width: 50%;
  background: #dbdbdb;
  text-align: center;
}

table tr:nth-child(2n+1) {
  position:relative;
  display:block;
  height:20px;
  background:green;
}

table tr:nth-child(2n+1) td {
  position:absolute;
  left:0;
  right:-100%;
  width: auto;
  top:0;
  bottom:0;
  background:red;
  text-align:center;
}
<table>
    <tr>
        <td>row</td>
    </tr>
    <tr>
        <td>cell</td>
        <td>cell</td>
    </tr>
    <tr>
        <td>row</td>
    </tr>
    <tr>
        <td>cell</td>
        <td>cell</td>
    </tr>
</table>
passatgt
  • 4,234
  • 4
  • 40
  • 54
-1

You could always position:absolute; things and specify widths. It's not a very fluid way of doing it, but it would work.

Joe
  • 3,804
  • 7
  • 35
  • 55
doubleJ
  • 1,190
  • 1
  • 16
  • 29
  • There are far more ways to achieve this than to use bad markup. Absolute positioning to force a layout has always been considered poor practice. – MistyDawn Aug 15 '19 at 20:46
-1

Media Query classes can be used to achieve something passable with duplicate markup. Here's my approach with bootstrap:

  <tr class="total">
    <td colspan="1" class="visible-xs"></td>
    <td colspan="5" class="hidden-xs"></td>
    <td class="focus">Total</td>
    <td class="focus" colspan="2"><%= number_to_currency @cart.total %></td>
  </tr>

colspan 1 for mobile, colspan 5 for others with CSS doing the work.

tomrozb
  • 25,773
  • 31
  • 101
  • 122
DigitalDesignDj
  • 1,725
  • 15
  • 16
  • The asker specifically stated he could not use HTML elements. If he could, this would be an easy problem to solve.
    – MistyDawn Aug 15 '19 at 20:43
-1

I've created this fiddle:

enter image description here

http://jsfiddle.net/wo40ev18/3/

HTML

<div id="table">
<div class="caption">
    Center Caption
</div>
<div class="group">
      <div class="row">
            <div class="cell">Link 1t</div>
            <div class="cell"></div>
          <div class="cell"></div>
          <div class="cell"></div>
            <div class="cell"></div>
            <div class="cell ">Link 2</div>
      </div>
</div>

CSS

   #table {
    display:table;
}

.group {display: table-row-group; }

.row {
    display:table-row;
    height: 80px;
    line-height: 80px;
}

.cell {
    display:table-cell;
    width:1%;
    text-align: center;
    border:1px solid grey;
    height: 80px
        line-height: 80px;
}

.caption {
    border:1px solid red; caption-side: top; display: table-caption; text-align: center; 
    position: relative;
    top: 80px;
    height: 80px;
      height: 80px;
    line-height: 80px;

}
Layke
  • 51,422
  • 11
  • 85
  • 111