I am trying to get a horizontal line to stretch between the first and last columns in a table but I need the first and last columns to wrap if the text is long. The only way I have found to get the desired effect is to use width:100%; on the middle column, and white-space:nowrap; on the first and last, but I need to find another way as I need the text to wrap when there isn't enough space. Is there a way to achieve this effect in plain CSS?
https://jsfiddle.net/macu/8axk5qv5/4/
table {
width: 100%;
}
td {
vertical-align: middle;
white-space: nowrap;
}
td:nth-child(2) {
width: 100%;
}
.line {
border-top: thin solid blue;
}
<table>
<tr>
<td>Title cell with a long title that should wrap</td>
<td><div class="line"></div></td>
<td>Another cell, should wrap</td>
</tr>
</table>
If the text is long enough there should be no line, and the text should wrap normally:
You can put a span or div in each cell, and make them to use white background, then set the line on the table row to create such layout visually.
Check out the fiddle demos below, so you can easily resize and see the wrapping text.
jsFiddle
.table {
width: 100%;
border-collapse: collapse;
}
.table tr {
background: linear-gradient(blue, blue) center/99.99% 1px no-repeat;
}
.table div {
background: white;
display: inline-block;
}
.middle div {
min-width: 100px; /*remove or adjust value as need*/
}
.last {
text-align: right;
}
<table class="table">
<tr>
<td class="first">
<div>Title cell with a long title that should wrap</div>
</td>
<td class="middle">
<div><!-- This td can be removed if no min-width needed --></div>
</td>
<td class="last">
<div>Another cell, should wrap</div>
</td>
</tr>
</table>
But using flexbox can make it much easier, if you don't have to use table.
jsFiddle
.container {
display: flex;
}
.line {
background: linear-gradient(blue, blue) center/1px 1px repeat-x;
flex: 1;
min-width: 100px; /*remove or adjust value as need*/
}
<div class="container">
<div>Title cell with a long title that should wrap</div>
<div class="line"></div>
<div>Another cell, should wrap</div>
</div>
try by removing the white-space: nowrap; on the TD tag, then target the first and the third TD with
td {
vertical-align: middle;
//white-space: nowrap;
}
td:nth-child(1),td:nth-child(3) {
//add whatever min-width AND max-width so it could be something like this
min-width:150px;
max-width:300px;
}
see if that helps.
Behavior of code snippet is different in Chrome 51.0.2704.103 and Firefox 47.0.1.
Please explain why this happens. Where behavior is correct, where not and why you think so. Thanks.
div,
td {
border: 1px solid black;
}
.container {
position: absolute;
}
.w100Pc {
width: 100%;
}
.nowrap {
white-space: nowrap;
}
<div class="container">
<div>Modal dialog header</div>
<table>
<tr>
<td class="w100Pc">rest of space column</td>
<td class="nowrap">content based width column</td>
</tr>
</table>
<div>Here goes main content what should stretch "container" width</div>
<div>Modal dialog footer</div>
</div>
Browser render the code differently i guess it's because they follow different standards, i think Firefox is rendering the code currently in you example and to make it look the same in both browsers just add display:block;
div,
td {
border: 1px solid black;
}
.w100Pc {
display:block;
width: 100%;
font-family:'Times New Roman';
}
.container {
position: absolute;
left: 200px
}
<div style="position: absolute; left:200px">
<table class="w100Pc">
<tr>
<td class="w100Pc">
w100Pc
</td>
<td>buttons</td>
</tr>
</table>
</div>
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?
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.
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.
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>
<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>
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>
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.
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'.
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>
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>
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>
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;
}
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>
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>
You could always position:absolute; things and specify widths. It's not a very fluid way of doing it, but it would work.
I've created this fiddle:
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;
}
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.
I have an example of the problem here:
http://jsfiddle.net/s6t3p/
I have the following markup:
<h1>Just Text</h1>
<table>
<tr>
<td class='cell'>Some Text</td>
<td class='cell'>More Text</td>
</tr>
</table>
<h1>With Icon Cell</h1>
<table>
<tr>
<td class='cell'>Some Text</td>
<td class='cell-ico'><div class='ico'></div></td>
<td class='cell'>More Text</td>
</tr>
</table>
And the following CSS:
table,td,tr
{
margin: 0; padding: 0;
border: none; outline: none;
font-size: 100%; font: inherit;
vertical-align: baseline;
}
table { border-collapse: collapse; border-spacing: 0;}
.cell
{
border:solid 1px #DDD; padding:0 5px; text-align:left;
line-height:27px;
}
.ico {width:24px; height:24px; background:#05F;}
I wish for each cell to be 27px in height. This is the case for the 1st table. But the second table which contains a cell with a 24px div has a height of 32px. I don't understand why. It seems like a 24x24 div should fit inside fine without increasing the cell height.
Can anyone explain why this is happening and how to fix it so that I can keep the cells at a height of 27px? I am currently testing with FireFox 29.
Thanks for any help.
If you are looking to display tabular data, then this is the way to go :)
The behaviour is caused by vertical-align: baseline;.
Just reset the vertical-align for .cell-ico and provide a set height. Give .ico a height of 100%.
Have a fiddle
.cell-ico {
height: 24px;
vertical-align: top;
}
.ico {
width:24px;
height: 100%;
background:#05F;
display: block;
}
try to add this inside your CSS
td{
vertical-align:middle;
height:27px;
}
Looks like vertical-align: baseline; applied to all tags table, tr, td is messing it up.
Remove it and try it out.
I'd suggest you use div elements with their respective display attributes set to either table, table-row, table-cell, etc. Instead of actual tables. The use of tables as a layout techique is discouraged since HTML4. This approach may be a little bulky, but for layout purposes it'll save you some trouble dealing with css.
Check this jsfiddle for example:
HTML:
<div id="Table">
<div class="row">
<div class="cell">Lorem ipsum</div>
<div class="cell">Lorem ipsum</div>
</div>
<div class="row">
<div class="cell">Lorem ipsum</div>
<div class="cell">Lorem ipsum</div>
</div>
</div>
<br/>
<br/>
<div id="Table">
<div class="row">
<div class="cell2"><div class="oddDiv">im inside a div</div></div>
<div class="cell2">Lorem ipsum</div>
</div>
<div class="row">
<div class="cell2">Lorem ipsum</div>
<div class="cell2">Lorem ipsum</div>
</div>
</div>
CSS:
#Table {
display: table;
width: 200px;
border-collapse: collapse;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
border: 1px solid blue;
height: 27px;
}
.cell2 {
display: table-cell;
border: 1px solid red;
height: 24px;
}
.oddDiv {
height: 24px;
width: 24px;
overflow: hidden;
}
Update, regarding semantics:
It's true that from a developer's point of view there's no difference between a table markup element and a generic container like a div with the appearance of a table in terms of layout and even code comprehension. But, there's no way for an accessibility tool, say, an screen reader, to discern between a bunch of div elements with different id's, unless the tool was proprietary or there was some kind of convention for special id's to use for this kind of purposes (which I doubt). So for layout purposes divs are the way to go, but if semantics are a concern, the use of tables is the best solution.
I need to create a layout that has a toolbar, a (variable height) tab line, a content view and an info view. The entire content must always fill the entire browser window, without causing a scrollbar to appear. Only the content and info panels can have scrollbars, and only when they overflow. My layout so far seems to be working in Chrome, but not in Firefox or Internet Explorer. I can't use absolute positions, because the tab line can vary in height, and I would really like to avoid using JavaScript for layout.
Right now I have this markup:
<body>
<table>
<tr>
<td colspan="2" class="toolbar">toolbar</td>
</tr>
<tr class="tabs">
<td colspan="2" class="tabs">tabs</td>
</tr>
<tr>
<td class="content">
<div>content content content content</div>
</td>
<td class="info">info</td>
</tr>
</table>
</body>
And this css:
html, body, body > table {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
box-sizing: border-box;
}
body > table {
border-collapse: collapse;
border-spacing: 0;
}
body > table > tbody > tr > td {
padding: 0;
vertical-align: top;
}
.toolbar { background-color: red; }
.tabs { background-color: green; }
.content {
background-color: blue;
height: 100%;
}
.content > div {
height: 100%;
overflow: auto;
}
.info {
background-color: yellow;
width: 300px;
}
It must look like this:
Try something like this fiddle
Its more complicated than a regular table layout using CSS, but should work for you with some tweaking.
HTML
<div class='viewport'>
<div class='caption'>
<div class='toolbar'>toolbar</div>
<div class='tabs'>tabs</div>
</div>
<div class='row'>
<div class='content'>content</div>
<div class='info'>info</div>
</div>
</div>
CSS
body, .viewport{
height:100%;
width:100%;
padding:0;
margin:0;
overflow:hidden;
}
.viewport{
display:table;
position:fixed;
height:100%;
}
.row{
display:table-row;
}
.caption{
display: table-caption;
}
.content, .info{
display:table-cell;
}
.toolbar{
background:red;
}
.tabs{
background:green;
}
.content{
background:blue;
}
.info{
background:yellow;
}