overflow: hidden on table causes bottom and right border to dissappear - html

As the title says my table border is being cut off on my table when using overflow: hidden. Please see code below for example.
<style>
table {
border-collapse: collapse;
}
table {
border: 1px solid black;
overflow: hidden;
}
</style>
<body>
<table>
<thead>
<tr>
<th>header 1</th>
<th>header 2</th>
<th>header 3</th>
</tr>
</thead>
<tbody>
<tr>
<th>side header</th>
<td>data 1</td>
<td>data 2</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>footer header</th>
<td>footer 2</td>
<td>footer 3</td>
</tr>
</tfoot>
</table>
</body>
</html>
I have simplified my example down the the bare minimum. I could lose the border-collapse style which would correct this, but I need that style. My code becomes to messy without it.
As an interim solution I have found that I can hack it using the css below, but I am not a hug fan of hacks!
.borderhack:after {
content: '\00a0';
position: absolute;
border: 1px solid black;
left: -2px;
top: -2px;
width: 100%;
height: 100%;
z-index: -10;
}
table {
position: relative;
}
I would appreciate any explanations or better solutions to this. I am really interested to know why it's actually doing this after a days worth of investigation.
Thanks

There are two quick solutions:
Use 2px border width.
Use outline instead of border.
Eg:
table {
border-collapse: collapse;
border: 2px solid black;
overflow: hidden;
}
or
table {
border-collapse: collapse;
outline: 1px solid black;
overflow: hidden;
}
http://jsfiddle.net/6NVtS/1/
The why of it happening, I think, is that when using the collapsed border model of table borders the browser is trying to split the border in the center. On a one-pixel outside border obviously that's not possible, so the browser is using a full pixel width if top/left, and nothing if bottom/right. This behavior might be somewhere in the standards, I didn't look that far. But inside this will correctly fill out the borders without doubling up width, it's just the combination of the outside and overflow:hidden that's presumably cropping the bottom and right, which the browser generates but are technically nudged a half-pixel to the right and thus are 'outside' the region of the element. I hope that makes sense. Outline is not cropped by the overflow - I'm not sure why, I wouldn't have predicted an exception.
http://www.w3.org/TR/CSS21/tables.html#collapsing-borders
Another solution might be to apply overflow to td and th instead of table, or check if you really need to set overflow at all.

What's the point in using border-collapse if there are no borders to collapse? Remove the border-collapse and you'll be fine.
See working example here: http://jsfiddle.net/86xST/

Thanks to skrivener and some further investigation I have managed to figure this out. See the solution here.
Problem - border collapsing not equal around table border:
.table1 {
border : 3px solid black;
overflow : hidden;
border-collapse : collapse;
}
Solution - must not declare border width in border must do it using border-width:
.table2 {
border : solid black;
overflow : hidden;
border-collapse : collapse;
border-width : 6px 7px 7px 6px;
}
th {
border: 1px solid black;
}
th {
border: 1px solid black;
}
Problem:
<table class="table1">
<thead>
<tr>
<th>header 1</th>
<th>header 2</th>
<th>header 3</th>
</tr>
</thead>
<tbody>
<tr>
<th>side header</th>
<td>data 1</td>
<td>data 2</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>footer header</th>
<td>footer 2</td>
<td>footer 3</td>
</tr>
</tfoot>
</table>
Solution:
<table class="table2">
<thead>
<tr>
<th>header 1</th>
<th>header 2</th>
<th>header 3</th>
</tr>
</thead>
<tbody>
<tr>
<th>side header</th>
<td>data 1</td>
<td>data 2</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>footer header</th>
<td>footer 2</td>
<td>footer 3</td>
</tr>
</tfoot>
</table>
Skrivener:
"The why of it happening, I think, is that when using the collapsed
border model of table borders the browser is trying to split the
border in the center. On a one-pixel outside border obviously that's
not possible, so the browser is using a full pixel width if top/left,
and nothing if bottom/right."
This let me to believe that perhaps if I just set the 4 borders setting border-width manually and added 1px to the right and the bottom, the rounding would work correctly. See the solution and you can update the borders to see it works correctly. Now no matter what you can have equal width outer borders as long as you add 1px to the right and bottom borders.
Thanks again for all the help!

Try following
1. give margin to your table
2. User table-layout: fixed
3. set

Related

How to get a table row to extend to 100% width when child cells do not span the full width of the table (Picture included)

The only solution I have found is to fill in the table with empty table cells (Shown in ROW1 and ROW7)
ROW3 through ROW6 contain only a single table cell which does not span the full table width. I've tried a fixed layout table and everything I can think of on the table-row to get it to fill in to 100% width without luck.
The reason I need the row to be full width is so that I can show top and bottom borders on the row, spanning the full width of the table.
I'm working on updating software for a client and must use tables and must find a solution that is compatible in Internet Explorer 10 minimum.
All table related elements use their natural display types, table, table-row, and table-cell
The rows are generated programmatically and colspan is a problematic solution.
Thank you for reading.
You cannot apply a border on table rows, but you can apply an outline:
tr {
outline: 1px solid black;
}
Example 1:
table {
border: 1px solid black;
border-spacing: 0;
empty-cells: show;
}
td, th {
padding: 0.5em;
border-right: 1px solid #ddd;
}
tr {
outline: 1px solid black;
}
<table>
<tr><th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 6</th>
<th>Col 7</th>
</tr>
<tr><td>Row1</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Row2</td>
</tr>
<tr><td>Row3</td>
</tr>
</table>
As you pointed out in the comments, an outline surrounds the entire element.
To have a single border at the bottom of the row, put it on a pseudo-element:
table {
position: relative; /* pseudo-element will be based on the table's position */
overflow: hidden; /* don't let the pseudo-element overflow the table */
}
tr:before {
content: ''; /* required for rendering */
position: absolute; /* absolute positioned */
width: 100%; /* span the entire table */
border-bottom: 1px solid black; /* the magic border */
}
Example 2:
table {
border: 1px solid black;
border-spacing: 0;
empty-cells: show;
}
td, th {
padding: 0.5em;
border-right: 1px solid #ddd;
}
table {
position: relative; /* the pseudo-element will be based on the table */
overflow: hidden; /* don't let the pseudo-element overflow */
}
tr:before {
content: ''; /* required for rendering */
position: absolute; /* absolute positioned */
width: 100%; /* span the entire table */
border-bottom: 1px solid black; /* the magic border */
}
<table>
<tr><th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 6</th>
<th>Col 7</th>
</tr>
<tr><td>Row1</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr><td>Row2</td>
</tr>
<tr><td>Row3</td>
</tr>
</table>
Apply colspan on the cell:
<table border="1">
<tr>
<td>oi</td>
<td>oi</td>
<td>oi</td>
<td>oi</td>
<td>oi</td>
</tr>
<tr>
<td colspan="5">oi</td>
</tr>
<tr>
<td>oi</td>
<td>oi</td>
<td>oi</td>
<td>oi</td>
<td>oi</td>
</tr>
</table>

Why are table borders not collapsing when caption is positioned?

In this fiddle http://jsfiddle.net/jnddfyeq/ I have two tables with border-collapse: collapse. In the first one everything works as expected. In the second one I position the caption with position: absolute and now the borders between the thead and tbody do not collapse.
This happens in Firefox 38 and IE8 (not in a fiddle.) I have not tested other browsers. Is this behavior standard? If so why?
UPDATE: Same thing happens in Safari.
It's not really that the borders don't collapse. It seems that what's happening is that even if the caption is displayed out of the table, there is still an invisible cell being added to the table.
The specification mention that this can happen, it's not exactly clear what should happen in this case, but it's clear that a table follows a pretty strict layout structure and that it will compensate in the background when messing with that layout. See:
Note. Positioning and floating of table cells can cause them not to be
table cells anymore, according to the rules in section 9.7. When
floating is used, the rules on anonymous table objects may cause an
anonymous cell object to be created as well.
Here: http://www.w3.org/TR/CSS2/tables.html#table-layout
If you look at the computed style of your absolute caption you'll see it's not a cell anymore, so it's probably replaced by an anonymous cell. And I guess that since table head are always at the top by definition, this anonymous cell is placed automatically below it, in the table body group. If you set coordinates to 0, you'll see exactly where it ends up. And if you play with borders, you'll see also what happens.
See snippet:
console.log('first caption:', window.getComputedStyle(document.getElementsByTagName('caption')[0]).display, '\nabsolute caption:',
window.getComputedStyle(document.getElementsByTagName('caption')[1]).display)
body
{
margin: 0;
}
table {
border-collapse: collapse;
margin-bottom: 1em;
border-spacing: 12px;
background-color: yellow;
margin-left: 0px;
}
th {
padding: 0.5em;
border: 10px dotted green;
background: #8cf;
}
td {
padding: 0.5em;
border: 15px dotted red;
background: #8cf;
}
caption.abs {
position: absolute;
left: 0;
}
tr
{
background-color: pink;
}
table.realnoncollapse {
border-collapse: separate;
margin-bottom: 1em;
border-spacing: 12px;
background-color: yellow;
}
<table>
<caption>Chill Table</caption>
<thead>
<tr id="tr1">
<th>Chiller</th>
<th>Chillness</th>
</tr>
</thead>
<tbody>
<tr>
<td>The Dude</td>
<td>Way chill</td>
</tr>
<tr>
<td>This Guy</td>
<td>Pretty chill</td>
</tr>
</tbody>
</table>
<table>
<caption class="abs">No chill</caption>
<thead>
<tr >
<th>Chiller</th>
<th>Chillness</th>
</tr>
</thead>
<tbody>
<tr>
<td>The Dude</td>
<td>Way chill</td>
</tr>
<tr>
<td>This Guy</td>
<td>Pretty chill</td>
</tr>
</tbody>
</table>
<table class="realnoncollapse">
<caption class="abs">No chill</caption>
<thead>
<tr >
<th>Chiller</th>
<th>Chillness</th>
</tr>
</thead>
<tbody>
<tr>
<td>The Dude</td>
<td>Way chill</td>
</tr>
<tr>
<td>This Guy</td>
<td>Pretty chill</td>
</tr>
</tbody>
</table>

Why do the CSS property border-collapse and empty-cells conflict?

I can use the CSS property border-collapse to combine the borders of adjacent table cells. And I can use empty-cells to hide table cells that have no content. But when I use both, the empty-cells property has no effect and empty cells are always visible. At least there's a border around each of them, even where multiple adjacent rows and columns are empty.
Here's an example:
<!doctype html>
<html>
<head>
<style>
table
{
border-collapse: collapse;
border-spacing: 0;
}
th,
td
{
empty-cells: hide;
border: solid 1px black;
padding: 2px 4px;
}
</style>
</head>
<body>
<table>
<tr>
<th></th>
<th></th>
<th>Header 3</th>
</tr>
<tr>
<th></th>
<th></th>
<th>Header 3</th>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td></td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td></td>
</tr>
</table>
</body>
</html>
As #Bolt explained why this happens, I will provide a solution for this, you can use the below snippet in your CSS to hide the empty cells
th:empty, td:empty {
border: 0;
}
Demo
Using :empty pseudo, I set the border: 0; so physically the element is present on the page, we just target the styles of the empty cells and set the borders to 0.
I didn't used display: none; as it will spoil your table layout, so using the above snippet is enough if you want to keep the border collapsed.
Note: The selector am using is a general selector and will target globally, if you want to target the element specifically, consider using a class instead like
.table_class_name th:empty,
.table_class_name td:empty {
/* Styles goes here */
}
This is a trick that I found, you can use border-collapse as separate. then you define border-spacing to 0px into your table then define the padding in your td to 0px.
table
{
empty-cells: hide;
border-collapse: separate;
border-spacing: 0px;
}
td
{
border: thin solid black;
text-align: right;
padding: 0px;
}
th
{
border: thin solid black;
background-color: yellow;
}

Wrong table header border in Firefox

I would like to know, if this is a bug. As you can see on jsfiddle, there is only top border instead of borders around all cells. Note that IE 9 draws borders as expected. Also note that if you move the content of <tfooter> in the <tbody>, Firefox starts drawing borders as IE.
HTML
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="3">
<span class="norecords">No records found.</span>
</td>
</tr>
</tfoot>
<tbody></tbody>
CSS
table {
background-color: #EFEFEF;
border: 1px solid #BCBCBC;
border-collapse: collapse;
}
th, td {
padding: 10px;
}
th {
border: 1px solid #BCBCBC;
}
Your problem is the tbody - if you remove this empty tag (or add a row to it) it will work :
http://jsfiddle.net/FyARs/3/
This works for all
<table border=0 cellspacing=0 cellpadding=0>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="3">
<span class="norecords">No records found.</span>
</td>
</tr>
</tfoot>
<tbody></tbody>
</table>
CSS
table {
background-color: #EFEFEF;
border: 1px solid #BCBCBC;
}
th, td {
padding: 10px;
}
th {
border: 1px solid #BCBCBC;
}
It because the different ways browsers dealing with collapse borders.
In firefox, an empty tbody without tr in it, it will be treated as no-border, the no-border edge will over the edge of nearly rows.
just remove unused tbody in your case, or put at least a pair of <tr></tr> in it.

CSS solution to positioning Span element on a Table element

I am trying to position a span element relative to the upper-right corner of a table object.
This table may be wider or move around based on what the user does on the tool, so I was looking for something simpler than the jQuery.position method. I was hoping to do something elegant with CSS.
I've built a small example of my dilemma in jsfiddle: http://jsfiddle.net/xerf/ZSGfc/
<div>
<table>
<thead>
<tr>
<th colspan="3">Title</th>
</tr>
</thead>
<tbody>
<tr>
<td>Stuff 1</td>
<td>Stuff 2</td>
<td>Stuff 3</td>
</tr>
<tr>
<td>Stuff 1</td>
<td>Stuff 2</td>
<td>Stuff 3</td>
</tr>
<tr>
<td>Stuff 1</td>
<td>Stuff 2</td>
<td>Stuff 3</td>
</tr>
</tbody>
</table>
<span>×</span>
</div>
Below are the CSS Styles
body
{
font-family:sans-serif;
}
table
{
border-collapse: collapse;
border: 1px solid black;
margin: 20px;
}
th
{
padding: 6px;
}
td
{
padding: 3px;
border: 1px solid black;
}
UPDATE: Added some images to show required positions:
Needs to be where the red Square appears above
I wrapped your span in a div and placed it in the <th> with your title:
<th colspan="3"><div id="container">Title
<span>×</span></div></th>
css:
#container{
width:auto;
height:auto;
position:relative;
}
span{
position:absolute;
right:0px;
top:0px;
Here is a demo: http://jsfiddle.net/ZSGfc/6/
A very simple way would be to simply add another row to the very top of the table, removing its left, top and right borders. Then move your span so that it is contained by this new row and align the text to the right.
I would recommend using the div or adding another div that will control the width of the table, and then have the table inherit the width of that div. From there make the div's position property set to relative. Then you can absolutely position the span on the div.
Something similar to this fiddle. With some tweaking.
Try this:
div{
position:relative;
width: XXXpx;
}
table{
width: XXXpx;
}
span{
position: absolute;
top: 0px;
right: 0px;
}
an additional table cell on top with colspan="3" and text-align:right would work.