23

I am a bit puzzled right now, because I had CSS code that worked, but it wasn't beautiful at all. I now want to rework this CSS styles and build them via LESS. And I have big problems with display:table; / display:table-row; and display:table-cell;.

For example I have the following code: http://jsfiddle.net/La3kd/2/

How can I do it that the last cell (center) does not shift the above second cell to the right? The last cell should have the width of the 2 cells above. Some kind of colspan is needed. It is so weird, because I have the impression that it worked before I reworked the code. But now all elements to the right are totally shifted.

James Jithin
  • 10,183
  • 5
  • 36
  • 51
Torben
  • 5,388
  • 12
  • 46
  • 78
  • Possible duplicate of [DIV table colspan: how?](http://stackoverflow.com/questions/4746061/div-table-colspan-how) – naXa stands with Ukraine Oct 25 '16 at 14:41
  • Possible duplicate of [Colspan/Rowspan for elements whose display is set to table-cell](https://stackoverflow.com/questions/9277661/colspan-rowspan-for-elements-whose-display-is-set-to-table-cell) – GSerg Aug 10 '20 at 10:13

9 Answers9

32

CSS has no colspan analog. Based on your example, you can just mark up your last row as a separate nontably block.

You could also use display: table-caption in conjunction with caption-side: bottom to display the table row as a last “row” that spans all columns. See live demo.

Marat Tanalin
  • 13,927
  • 1
  • 36
  • 52
  • 1
    Wouldn't that be abusing CSS? – Mr Lister Mar 24 '12 at 12:25
  • 2
    Yes. Everybody talks about how using tables for non-tabular data is table abuse. Well, I want to state for the record that I believe using `display:table-caption` for non-table-captions is CSS abuse. – Mr Lister Mar 24 '12 at 12:30
  • `display: table-caption` (as well as `display: table-footer-group/table-header-group`) can be quite useful for changing vertical order of blocks. Each feature has its own applicability. – Marat Tanalin Mar 24 '12 at 12:39
  • 4
    Note: the `display: table-caption` always displays that row at the bottom, regardless of the order in the "table" See modified example: http://jsfiddle.net/La3kd/18/ – allicarn Feb 01 '13 at 15:00
1

One idea would be to leverage absolute positioning. Relative position a wrapper around the table, then all absolute positioning becomes coordinate centric to the wrapper. See below. Notice I define a class of tableWrapper which will be set position:relative, then define class of tableRow and - I'm assuming you'll set .tableRow div { display: table-cell; } so I didn't bother putting a class on each div. You'll have to find a way to prevent it from overlapping the div below it if it's height gets larger than the 2nd div. Should be very doable.

<div class="tableWrapper">
  <div class="tableRow">
    <div>Column 1</div>
    <div>Column 2</div>
  </div>

  <div class="tableRow">
      <div style="border: 1px solid black; position: absolute; width: 100%;">appears like colspan=2</div>
      <div>&nbsp; (only here to force a row break before the next table row)</div>
  </div>

  <div class="tableRow">
    <div>Column 1</div>
    <div>Column 2</div>
  </div>
</div>
1

Use a real table when you are forced to do so to get the layout you want.

The ONLY necessary reason to not use a table for layout is that a speaking browser for the blind gives the row number and column number coordinates of each table cell. This confuses the blind reader when table cells are used for layout.

Of course, it is much easier to use margins, borders, and padding where they do the job much better than faking them with tables, but when you have something with a layout similar to a newspaper want-ad page, it is better to use a real table, a set of nested tables, or a table full of divs.

I will always use div or div faking a table with display table parts when they work.

When they do not work, or when the div layout falls apart at different screen resolutions, I will use a real table. It never falls apart.

This kludgery by the W3C would have had a better solution with a CSS code to tell the speaking browser to not treat a real table as a table.

I also treat a table of comments arranged around the page title as tabular data, even though it is not numeric. Tabular data can include categorical data.

One idea is to hide (with same foreground and background colors) a disclaimer telling the blind person to ignore the table coordinates the speaking browser provides because the use of a table was forced by the lack of ability to make the layout work with divs.

midimagic
  • 45
  • 1
1

Depending on your needs, flexbox layout may accomplish what you are looking for.

div.table{
  display:block;
  width:100%;
}

div.table >div{
  display:flex;
  width:100%;
  border:1px solid gray;
  flex-direction:horizonal;
}
div.table > div >div{
  display: block;
  flex-grow:1;
  border-bottom:1px solid #ddd;
  vertical-align: middle;
  height:30px;
  padding:4px;
}

See demo:

http://jsbin.com/mimegodiba/edit?html,css,output

user3413723
  • 11,147
  • 6
  • 55
  • 64
1

When I needed colspan I used "display: grid" instead, and defined the columns using grid-template-areas. There's a brilliant example here: https://css-tricks.com/snippets/css/complete-guide-grid/ (look for grid-template-areas)

Oranit Dar
  • 1,539
  • 18
  • 17
0

The table-caption is a good idea if you need header and footer row regardless of columns width... The absolute positioning works great except when your text is line-feeding at least once more than other cells in that row...

So here's a pseudo solution to have header in between rows of a responsive table and be sure to have line-feed according to the table header content (which is important if the table is populated dynamically). I've also included a sort of colspan as well (although not line-feeding accurately) :

CSS :

.table
{   display:table;
    position:relative;
}
.table > .header
{   display:table-caption;
    position:absolute;
    left:0;
    right:0;
}
.table > .l50{right:50%;}
.table > .r50{left:50%;}

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

.table > .row > *{display:table-cell;}

/* We add an extra cell where neededed to allow or header repositioning using % instead of fixed units */
.table > .header + .row > :last-child
{   width:1%;
    max-width:1px;
    overflow:hidden;
    visibility:hidden;
}

.table > .header + .row > :last-child > div
{   float:left;
    display:inline;
    visibility:hidden;
    width:10000%;/* 100% = parent element width (1%) ⇒ 100*100% = gran-parent element width*/
}
.table > .header + .row > :last-child > div > .l50
.table > .header + .row > :last-child > div > .r50{width:5000%;}

/* No responsive line-feed thought it's possible using % to estimate the size the span should take but it's not accurate (see HTML render) */
.table > .row > div > .span{position:absolute;left:0;right:33%;}
/* THIS MAKES SURE TRADITIONAL CELLS ARE VISIBLE */
.table > .row > .top
{   position:relative;
    z-index:1;
}

http://jsfiddle.net/sp2U4/

llange
  • 757
  • 2
  • 10
  • 14
0

I found a solution using jquery and table-layout: fixed. Here is my fiddle: http://jsfiddle.net/emilianolch/5nvxv5ko/

HTML:

<div class="table">
    <div class="table-row">
        <div class="table-cell">
            top left cell
        </div>
        <div class="table-cell">
            top right cell
        </div>
    </div>
    <div class="table-row">
        <div class="table-cell colspan">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
        </div>
    </div>
    <div class="table-row">
        <div class="table-cell">
            bottom left cell
        </div>
        <div class="table-cell">
            bottom right cell
        </div>
    </div>
</div>

CSS:

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

.table-row {
    display: table-row;
    border-collapse: collapse;
}

.table-cell {
    display: table-cell;
    padding: 5px;
    border: 1px solid black;
}

.table-cell.colspan {
    display: none;
    /* collapse border */
    margin-top: -1px;
    margin-bottom: -1px;
}

JS:

var rowWidth = $('.table-row:first').width();
var colWidth = $('.table-cell:first').width();
var marginRight = colWidth - rowWidth + 11;
$('.table-cell.colspan').css('margin-right', marginRight + 'px').show()
Ryan McDonough
  • 9,732
  • 3
  • 55
  • 76
emilianolch
  • 177
  • 6
-1

I could achieve the col-span with the table-row-group

div {
    border: solid 1px;
    min-width: 10px;
    min-height: 10px;
}

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

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

.table-cell {
    display: table-cell;
}

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

.table-cell-group {
    display: table-row;
}
<div style="display: table;">
  <div class="table-head">
    <div class="table-cell">h1</div>
    <div class="table-cell">h2</div>
  </div>
  <div class="table-row">
    <div class="table-cell">c1</div>
    <div class="table-cell">c2</div>
  </div>

  <div class="table-row-group">
    <div class="table-cell-group">
      cc
    </div>
  </div>

  <div class="table-row">
    <div class="table-cell">c1</div>
    <div class="table-cell">c2</div>
  </div>

  <div class="table-row">
    <div class="table-cell">c1</div>
    <div class="table-cell"></div>
  </div>


</div>
Ahmed Ahmed
  • 1,036
  • 11
  • 16
  • Your answer does not work, unfortunately. If you changed the `cc` in your example to something longer you would see that it still stays entirely within the first column. – Stanislav Pankevich Oct 10 '20 at 23:06
-2

CSS3 has a column-span attribute. But please try to use flexbox or css grid for layout.

fabb
  • 11,660
  • 13
  • 67
  • 111