Can overlapping colspan on table cells shrink-to-fit? - html

I can’t figure this one out for the life of me. Take a table that has 2 rows, each with 2 cells. The top-right and bottom-left cells are set to colspan="2" (so the table really has 3 columns). If the non-colspan cells have a 100×100 image inside, and the colspan cells have a 200×100 image, you’d expect the table width to be something like 300, right? Nope nope nope! It’s more like 400.
See this pen: http://codepen.io/sandwich/pen/apYPdL
It seems like the colspan’d cells are greedy for width, which goes contrary to typical table sizing of shrinking the cells to fit the content.
Can anyone shine a light on this behavior? In the pen, the desired result is for the first two rows to size themselves like they do when the third row is added, but without the third row having to be added.

If the non-colspan cells have a 100×100 image inside, and the colspan cells have a 200×100 image, you’d expect the table width to be something like 300, right?
Well probably if the <table> had border-collapse:collapse but as it is separate and 20px left and right borders , that's 80px extra for 2 columns. that's 380px at minimum.
Try table-layout:fixed the default is auto. Using fixed will allow you more control of a table's behavior.
CODEPEN
SNIPPET
// Toggle visibility of 3rd row, which has no spanned cells.
$(".toggle_3rd_row").click(function() {
$(".row_3").fadeToggle();
});
// Toggle applying CSS widths to <td>s
$(".toggle_widths").click(function() {
$("table").toggleClass("defined_sizes");
})
body {
padding: 20px;
}
img {
display: block;
}
table {
width: 400px;
margin: 20px 0;
table-layout: fixed;
}
table.defined_sizes .cell_1-1 {
width: 100px;
}
table.defined_sizes .cell_1-2 {
width: 220px;
}
table.defined_sizes .cell_2-1 {
width: 220px;
}
table.defined_sizes .cell_2-2 {
width: 100px;
}
table .row_3 {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="toggle_3rd_row">Toggle third row</button>
<button class="toggle_widths">Toggle cell widths in CSS</button>
<table border="1" cellpadding="0" cellspacing="20">
<caption>Why do the cells only size properly with the colspan-less third row present??</caption>
<tr>
<td class="cell_1-1">
<img src="http://placehold.it/100x100?text=100w">
</td>
<td colspan="2" class="cell_1-2">
<img src="http://placehold.it/222x100?text=222w">
</td>
</tr>
<tr>
<td colspan="2" class="cell_2-1">
<img src="http://placehold.it/222x100?text=222w">
</td>
<td class="cell_2-2">
<img src="http://placehold.it/100x100?text=100w">
</td>
</tr>
<tr class="row_3">
<td>
<img src="http://placehold.it/100x100?text=100w">
</td>
<td>
<img src="http://placehold.it/100x100?text=100w">
</td>
<td>
<img src="http://placehold.it/100x100?text=100w">
</td>
</tr>
</table>

Related

HTML CSS Three Column Layout, with a twist

I need a 3 column layout in HTML/CSS, but different from anything I can find on here.
What I'm really struggling to achieve:
3 Col table with a fixed width of 740px:
A fluid left column (this should expand/contract with whatever space is left)
A fixed width middle column (130px)
Auto-width right column (which is only as wide as the content, must not wrap text)
Is this even do-able? I've seen exmples of this with a fluid left, fixed right but i didn't know how to then add a 3rd auto-width column
Been driving me nuts for ages!
Added complication: Any CSS style needs to be inline, this is for an HTML email!
Thanks folks.
First of all please see the Help Center article on creating a Minimal, Complete, and Verifiable example. You should be trying out your own solution before posting here for help.
To get you started I created a quick codepen example of what you're looking for. The left section will use whatever space is available. The middle section will always be 130px and the right section will fit the width of whatever content you have. Let me know if you have any questions.
HTML
<table border="1" width="740px">
<tr>
<td>
left
</td>
<td class="middle">
middle
</td>
<td class="right">
right - this will fit to your content
</td>
</tr>
</table>
CSS
.middle {
width: 130px;
}
.right {
width: 1%;
}
Edit:
I just saw your note on making the CSS inline. You would just add the relevant CSS to style tags within the HTML instead of having an external style sheet.
New HTML
<table border="1" width="740px">
<tr>
<td>
left
</td>
<td style="width: 130px;">
middle
</td>
<td style="width: 1%;">
right - this will fit to your content
</td>
</tr>
</table>
Okay i can't beleive i wasted hours trying to get this work, yet I randomly tried this and it DID work!
<table style="width:100%; max-width:740px;" height="65px" cellspacing=0 cellpadding=0>
<tr>
<td height="65px" style="background-color: cyan;">Left</td>
<td height="65px" width="130px" style="min-width:130px; max-width:130px; background-color: yellow;">Middle 130px</td>
<td width="1px" height="65px" style="background-color:green;">dynamic</td>
</tr>
</table>
https://jsfiddle.net/Murdo/5fn1z3g5/
Not sure that setting width to 100% and then limiting it to a max of 740 is the best way...
Or I could put a DIV with a width of 740 and then set the table to 100% width inside the div...
<div style="width:740">
<table style="width:100%" height="65px" cellspacing=0 cellpadding=0>
<tr>
<td height="65px" style="background-color: cyan;">Left</td>
<td height="65px" width="130px" style="min-width:130px; max-width:130px; background-color: yellow;">Middle 130px</td>
<td width="1px" height="65px" style="background-color:green;">dynamic</td>
</tr>
</table>
</div>
UPDATE: This works great in browser.. sadly, outlook does not like DIV width, any max-width or min width either. Back to drawing board!
you can do it easly with CSS flex model.
HTML
<div class="Container">
<div>COL 1
Im taking all the rest
</div>
<div>COL 2</div>
<div>
COL 3
I'm taking excatly what i need
</div>
</div>
CSS
.Container
{
width: 740px;
height: 300px;
display: flex;
background-color: green;
}
.Container div:first-child
{
background-color: red;
flex: 1 0 auto;
}
.Container div:nth-child(2)
{
background-color: yellow;
flex: 0 0 130px;
}
.Container div:nth-child(3)
{
background-color: blue;
flex: 0 0 auto;
}
and here with Inline style (for your mail)

Bootstrap Custom Table Widths

My question is a little bit different than what is already out there.
I'm trying to create a table which has a certain width. The table has 3 columns. I want the first two columns to have an automatic width, and the third column to fill the remaining space.
Here's what I have so far, it's not quite working. The columns all have equal width. I have tried to set width: auto !important on the whole table, but then the third column is not filling the remaining space.
.message-timestamp {
width: auto !important;
}
.message-nick {
width: auto !important;
}
<table class="table table-hover" style="float:left; width:74%">
<tr>
<td class="message-timestamp">2015-02-03 11:15:16</td>
<td class="message-nick">ResidentBiscuit</td>
<td class="message-text">This is just a message</td>
</tr>
<tr>
<td class="message-timestamp">2015-02-03 11:16:35</td>
<td class="message-nick">SomeNick</td>
<td class="message-text">I'm replying to ResidentBiscuit</td>
</tr>
</table>
And here's the Bootply.
Hopefully I understood what you wanted here. Try this:
.message-timestamp {
width: auto;
white-space: nowrap;
}
.message-nick {
width: auto;
white-space: nowrap;
}
.message-text {
width: 100%;
}
This will give you auto-fit for the first two columns (and I added white-space to prevent the text from wrapping) and the third fills the row up.
You can try the following code by giving fixed width to first two columns and remove table width auto from css.
<table class="table table-hover" style="float:left; width:100%">
<tbody>
<tr>
<td class="message-timestamp" style="width:10%">2015-02-03 11:15:16</td>
<td class="message-nick" style="width:10%">ResidentBiscuit</td>
<td class="message-text">This is just a message</td>
</tr>
<tr>
<td class="message-timestamp">2015-02-03 11:16:35</td>
<td class="message-nick">SomeNick</td>
<td class="message-text">I'm replying to ResidentBiscuit</td>
</tr>
</tbody></table>
Hope this helps

HTML table with variable, fixed, and remaining width

I need to create an HTML table with the following layout:
[Name] [Message] Date]
Where the width of [Name] should be the width of the longest name (Up to a max), [Date]should be a fixed width of 95px (And floating to the right), while [Message] should take the remaining width.
I've tried using multiple div's, but I can't get the result I need, and a table seems much simpler.
So far, the following isn't working:
<table style="width: 100%">
<tr>
<td style="width: 100%; max-width: 100px">NAME</td>
<td style="width: 100%">message</td>
<td style="width: 95px">TIME</td>
</tr>
<tr>
<td style="width: 100%; max-width: 100px">NAME OTHER</td>
<td style="width: 100%">message</td>
<td style="width: 95px">TIME</td>
</tr>
</table>
Edit 1 Seems as though this example has exactly what I need. Although I still think a table would be neater.
Edit 2 The [Message] needs to allow for multiline...
Edit 3 Here is a working sample of what I need (Exactly) based on the link in Edit 1
This cannot be done in CSS alone, due to the requirements. The first column should be flexible, which is easy (just prevent line breaks and let the column take its natural width), and setting the last column width is trivial, but telling the browser to use all the rest in the mid column (instead of expanding the first column too) cannot be done in CSS. If you set its width to 100%, things work the desired way in some browsers, but other browsers (like IE) treat it differently. You would require a width of something plus 100% plus 95px to equal 100%, which is of course impossible, and browsers handle this in different ways.
However, with a little bit of JavaScript the medicine goes down: do as outlined above, with 100%, then postprocess the table by setting the first column to a specific width in pixels (using the value allocated by the browser), remove the width: 100% setting, and set table layout to fixed—which means that the browser now has two columns width fixed width, total width set to 100%, and one column with no width set, so it is easy to it to allocate the remaining width to the mid column.
<style>
td:first-child { white-space: nowrap }
td:nth-child(2) { width: 100% }
td:nth-child(3) { width: 95px }
</style>
<table border cellspacing=0 style="width: 100%">
<tr>
<td style="">NAME</td>
<td style="">message</td>
<td style="width:95px">TIME</td>
</tr>
<tr>
<td>NAME OTHER</td>
<td>message</td>
<td>TIME</td>
</tr>
</table>
<script>
(function () {
var row = document.getElementsByTagName('tr')[0];
var cell1 = row.children[0];
cell1.style.width = cell1.clientWidth + 'px';
row.children[1].style.width = 'auto';
document.getElementsByTagName('table')[0].style.tableLayout = 'fixed';
})();
</script>
For simplicity, this code is based on the assumption that there are no other tables on the page. Modify as needed. The attributes border cellspacing=0 are there just make the cell widths more visible.
Update: This does not address the issue of setting a maximum width on the first column. That requirement is underdefined unless you specify what should happen if the width is exceeded (truncation, word wrap, wrap anywhere, wrap with hyphenation?).
try this code .
.test
{
max-width:100px;
}
<table style="text-align: center;">
<tr>
<th>NAME</th>
<th>message</th>
<th style="width: 95px">TIME</th>
</tr>
<tr>
<td class="test">NAME OTHER</td>
<td>message</td>
<td style="width: 95px">TIME</td>
</tr>
</table>
The following .css code provides the template for the attached picture:
table {
display: table;
width: 100%;
table-layout: fixed;
position: absolute;
top: 10px;
empty-cells: hide;
}
td.small:first-Child {
vertical-align: top;
width: 100px;
overflow: hidden;
text-overflow: ellipsis;
}
td.small:last-Child {
vertical-align: top;
width: 95px;
}
td.extend {
vertical-align: top;
word-wrap: break-word;
}
.userName a {
color: #9DC8FC;
}
<tr>
<td class="small userName">
<a title="Administrator" href="#">Administrator</a>
</td>
<td class="extend">
is it me you're looking for?
</td>
<td class="small">
10:14:01 AM
</td>
</tr>

Prevent a table in overflow:auto div from shrinking

I'm having a bit of an issue getting some stylesheet behavior that I want. I'm not even sure if it's possible. Basically I'm attempting to place a table with a variable number of cells with static cell width in a DIV with overflow: auto, and my goal is that when the tables width extends past the width of the container DIV that it becomes scrollable.
This isn't the case. The cells get shrunk together. A very basic representation (with inline styles for ease on this; not actually in the application haha) of the code:
<div style="width: 1000px; overflow-x: auto;">
<table>
<tr>
<td style="width:400px;">
This
</td>
<td style="width:400px;">
Should
</td>
<td style="width:400px;">
Scroll!
</td>
</tr>
</table>
</div>
Is there anyway I can do this with CSS, or am I going to have to go back to setting the width inline on a second div containing the table through calculations?
Works if you set the width on the table itself.
<table style="width:1200px;">
The td will always shrink to the necessary size, they won't push the table wider in that situation.
using CSS can done like below but make sure you use id or class for applying css if you have more then one table or div.
<style>
div { width: 400px; overflow-x: auto; }
table { width:1200px; }
table td { width:400px; }
</style>
<div>
<table>
<tr>
<td>
This
</td>
<td>
Should
</td>
<td>
Scroll!
</td>
</tr>
</table>
</div>
This should help
<table style="width: max-content;">

Two columns table : one as small as possible, the other takes the rest

I have a to-columns table in a div :
<div>
<table>
<tbody>
<tr>
<td class="action" >
<a> ✔ </a>
</td>
<td class="content">
<p>Bigger text...(variable size).......</p>
</td>
</tr>
<tr>
<td class="action" >
<a> ✔ </a><a> ✘ </a>
</td>
<td class="content">
<p>Bigger text...(variable size).......</p>
</td>
</tr>
... same structure in all the table
</tbody>
</table>
</div>
And I would like the "action" column to fit the content, and the "content" column to take the rest of available space. The "action" column would look better with a right align.
The table should also fit 100% of the container's width.
Is there a way of doing this without fixing the columns width ?
I tried with this:
table .action
{
width:auto;
text-align:right;
}
table
{
border-collapse:collapse;
border-spacing:0;
width:100%;
}
But the left column takes half of the table...
Giving the content td a 100% width will force it to take as much space as it can, so .content{ width: 100% } should work.
Also give the .action a white-space: nowrap to make sure the x and the checkmark stay next to each other. Otherwise the content will be able to take even more space and force the icons below each other.
table .action
{
width:auto;
text-align:right;
white-space: nowrap
}
table .content {
width: 100%
}
table
{
border-collapse:collapse;
border-spacing:0;
width:100%;
border: 1px solid
}
<table>
<tbody>
<tr>
<td class="action" >
<a> ✔ </a>
</td>
<td class="content">
<p>Bigger text...(variable size).......</p>
</td>
</tr>
<tr>
<td class="action" >
<a> ✔ </a><a> ✘ </a>
</td>
<td class="content">
<p>Bigger text...(variable size).......</p>
</td>
</tr>
</tbody>
</table>
Set the column width: 1px and white-space: nowrap.
This will try to make it 1px, but the nowrap will stop it from getting smaller than the widest element in that column.
I found this answer when trying to make one column of many as small as possible.
Giving the content td a 1% width will force it to take as little space as it can, so .content{ width: 1% } worked for me.
The bootstrapian way of doing this:
<div class="row">
<div class="col-sm-1"> content... </div>
<div class="col"> content... </div>
</div>
Basically you need to try out different things keeping in mind the following:
col-sm Small column
col-sm-1 Smallest column
col-sm-2 Slightly bigger than smallest column (Numbers go from 1 to 12)
col-md Medium sized columns (same numbering rule)
col-lg Large sized columns (same numbering rule)