border-collapse: collapse not working properly when scaling - css

I'm trying to remove the border of a table using border-collapse: collapse. It works great and as it should, but when I start doing transform: scale() to make it smaller, the borders magically appear again.
https://jsfiddle.net/ox11pvag/
table {
border-collapse: collapse;
-moz-transform: scale(0.6);
-moz-transform-origin: top left;
-o-transform: scale(0.6);
-o-transform-origin: top left;
-webkit-transform: scale(0.6);
-webkit-transform-origin: top left;
transform: scale(0.6);
transform-origin: top left;
}
Is there a way to force the borders to collapse no matter what? I assume overlapping them (negative margin) is a way, but it sounds so dirty.

When browser is scaling the table it is not making exact calculations for the width of td elements. As a result there is some gap between adjacent td elements and background of parent element is visible through this gap which looks like td elements have borders(But actually its gap, if you will apply some background-color on parent you will see it).
You can fix this by doing the following changes:
Remove background of tbody tr:nth-child(odd) and apply it to table.
Add 2px or 3px border-right having the color same as background on td inside even rows and inside thead.
Working snippet is below:
table {
border-collapse: collapse;
transform: scale(0.6);
transform-origin: top left;
background: #7892a1;
width: 70%;
}
thead {
height: 50px;
line-height: 50px;
}
tbody tr {
height: 50px;
line-height: 50px;
}
thead {
background: #d2dbe0;
}
thead th {
border-right: 2px solid #d2dbe0;
}
tbody tr:nth-child(even) {
background: #a5b7c0;
}
tbody tr:nth-child(even) td {
border-right: 2px solid #a5b7c0;
}
<table>
<thead>
<th>Something</th>
<th>Something 2</th>
<th>Something 3</th>
</thead>
<tbody>
<tr>
<td>Some data</td>
<td>Some more data</td>
<td>Most data</td>
</tr>
<tr>
<td>Some data</td>
<td>Some more data</td>
<td>Most data</td>
</tr>
<tr>
<td>Some data</td>
<td>Some more data</td>
<td>Most data</td>
</tr>
</tbody>
</table>

Related

Solution for jumping Safari table caption?

anyone has a solution for what appears to be a Safari bug? When a transform CSS is applied to a table content, the caption jumps to the end of table.
There was a hint using "will-change: transform" for the caption with similar case, but unfortunately it does not work here.
See codepen:
https://codepen.io/anon/pen/GxVWzV
HTML:
<table>
<caption>
Caption
</caption>
<thead>
<tr>
<th></th>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr onclick="collapse(this)">
<td></td>
<td>Cell</td>
</tr>
</tbody>
</table>
CSS
tbody tr > td:first-child:before {
content: ' ';
display: inline-block;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 6px solid black;
vertical-align: middle;
margin-right: .7rem;
transform: translateY(-2px);
transition: transform .2s ease-out;
pointer-events:auto;
}
tbody tr.collapsed > td:first-child:before {
content: ' ';
transform: rotate(90deg) translateX(-3px);
}
JS:
function collapse(e) {
e.classList.toggle("collapsed");
}
NOTE: Fixed in Safari 15.1
I encountered a similar issue with caption-side: top; in iOS Safari.
Try add the following CSS:
caption {
display: block;
}
I can't believe this isn't fixed by now.
What I did, in jQuery, is detach the caption and then reattach:
$('table').prepend($('caption').detach());

stacking context on table element(head and body)

I was stuck with one CSS stacking context issue, I simplified it to following simple case.
A simple table as following code, I translated header in order to achieve scrolling effect, while the header was always covered by those translated td cells.
I have read several articles, including that famous one "What No One Told You About Z-Index", and try to add both translate and z-index css properties on thead and tbody, and I 'guess' they should be in the same stacking context, so z-index will work, while I failed, does the failure due to table has some special constraints on stacking context? The only solution I can find now is switching thead and tbody position in the html by putting thead after tbody tag.
Full Case is here.
.m-table {
width: 40%;
font-size: 14px;
text-align: center;
border: 1px solid #e6eaf9;
background: #fafbff;
transform: translateY(0);
}
.m-table th,
.m-table td {
padding: 16px;
border: 1px solid #ddd;
background: #effff0;
}
.m-table th {
background: #e6eaf9;
}
.m-table thead {
transform: translateY(25px);
margin-bottom: 10px;
}
td label.u-angle {
display: inline-block;
width: 10px;
height: 10px;
background: #79c5ff;
transform: rotate(45deg);
}
<table class="m-table">
<thead>
<tr>
<th>Price</th>
<th>Algorithm Factor</th>
<th>Links</th>
</tr>
</thead>
<tbody>
<tr>
<td>$1,326</td>
<td>
<label class="u-angle"></label>
</td>
<td>
Detail
</td>
</tr>
</tbody>
</table>

How do I control the width of the last column?

When I add the width to the td it makes the th bigger.
If the last column has a lot of text but I don't want the width to show in the whole page, how do I control it?
I would still want to have the th be nowrap and the 'Replacement' and 'Additional test' will always be yes/no text.
I made a https://jsfiddle.net/6Lmt5vjc/
table.standardtable {
border: 1px solid #ddd;
}
table.standardtable th,
table.standardtable td {
padding: 5px 9px;
border-bottom: 1px solid #ddd;
border-left: 1px solid #ddd;
text-align: left;
color: #000;
}
table.standardtable th{
background-color: #f3f3f3;
font-weight: bold;
}
table.standardtable th.section1{
background-color: #04659D;
color: #fff;
border-bottom: 1px solid #044971;
}
Use css selectors to find the last <td> and apply a max-width to it:
table.standardtable tr td:last-child{ /* last-child returns the last instance of the td */
max-width:150px;
/* additional styles as required */
}
Fiddle demo
One thing to note on your fiddle, don't use <td> and <th> mixed. <th> is a table header, where as <td> is a regular cell. Although technically your markup works it is not good practice.
Valid table would be something like:
<table>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
If you want to alter the markup, use css classes instead.

How can I get wkhtmltopdf to display th and td background gradients?

I need to add background gradients to some td and th elements in page which gets converted to PDF, however I'm getting some very strange behavior from wkhtmltopdf, so when I do this:
table {
width: 100%;
border-collapse: collapse;
}
th {
height: 60px;
border: 1px solid Black;
}
td {
height: 100px;
background: -webkit-linear-gradient(top, #ccc 0%, #888 100%);
border: 1px solid Black;
}
<table>
<tr>
<th></th>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td></td>
</tr>
</table>
The height of the th seems to encroach on each subsequent td somehow. All is well if I remove the th or set its height to a whole multiple of the td height.
Anyone got any insight into what's going on here? My HTML is hard to change so I'm hoping to be able to get this working using CSS alone, or wkhtmltopdf settings.
Edit:
Some screenshots before the bounty expires:
Here's how it looks in a webkit browser:
Here's what wkhtmltopdf does to it:
And one further observation: it doesn't have to be a th to cause the problem, as changing it to a similarly targeted <td class='th'> will cause the same effect.
wkhtmltopdf still uses the old (deprecated) webkit gradient syntax. Try this:
-webkit-gradient(linear, left top, left bottom, from(#ccc), to(#888));
For me it was as simple as adding
background-repeat: no-repeat !important;
What you think about this?
<style>
.table {
width: 100%;
display:table;
border-collapse: collapse;
}
.tr {
height: 60px;
display:table-row;
border: 1px solid Black;
}
.td, .th{
height: 60px;
border: 1px solid Black;
display:table-cell;
background: -webkit-linear-gradient(top, #ccc 0%, #888 100%);
}
</style>
<div class="table">
<div class="tr">
<div class="th"></div>
</div>
<div class="tr">
<div class="td"></div>
</div>
<div class="tr">
<div class="td"></div>
</div>
</div>
Is better to use DIV instead of the tables. You can do same thing with small changes.
And is better for you to add CSS inline to HTML if you work PDF or send on email like template.
UPDATE:
You can do this:
<style>
table {
width: 100%;
border-collapse: collapse;
}
th {
height: 60px;
}
td{height: 100px;}
td, th {
background: -webkit-linear-gradient(top, #ccc 0%, #888 100%);
border: 1px solid Black;
}
</style>
<table>
<tr>
<th></th>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td></td>
</tr>
</table>
or jQuery to replace tables with nested divs:
<style>
.table {
width: 100%;
display:table;
border-collapse: collapse;
}
.table .tr{
display:table-row;
}
.table .th{
height: 60px;
font-weight:bold;
}
.table .td{height: 100px;}
.table .th,
.table .td {
border: 1px solid Black;
display:table-cell;
background: -webkit-linear-gradient(top, #ccc 0%, #888 100%);
}
</style>
<table>
<tr>
<th>a</th>
</tr>
<tr>
<td>b</td>
</tr>
<tr>
<td>c</td>
</tr>
</table>
<script>
$(document).ready(function(){
$("table").each(function(a,table){
var i=a;
$(table).after('<div class="table" id="table-'+i+'"></div>');
var currentTH = $(this).parent().find('th');
$(currentTH).each(function(){
var content=$(this).html();
$('#table-'+i).append(' <div class="tr"><div class="th">'+content+'</div></div>');
});
var currentTD = $(this).parent().find('td');
$(currentTD).each(function(){
var content=$(this).html();
$('#table-'+i).append(' <div class="tr"><div class="td">'+content+'</div></div>');
});
$(this).remove();
});
});
</script>
We had to upgrade wkhtmltopdf due to security reasons and we experienced the same problem, however after struggling with CSS I managed to find a solution that worked for us, for example, the following CSS:
.TableRecords_Header {
color:#EAEAEA;
font-weight: normal;
background: #0F5D85 url(/RichWidgets/img/bar_gradient.png);
white-space: nowrap;
line-height: 18px;
padding: 4px 6px 4px 6px;
border-right: 1px solid white;
font-size: 14px;
}
Applied to any table <th> or <tr> cells, renders something like this:
Gradient Bug
It turns out that this version of webkit has problems handling "repeat-x" CSS property, so, to solve this issue I have used this CSS3 Equivalent:
.TableRecords_Header {
background-repeat: no-repeat !important;
background-size: 100% 23px !important;
}
Where background-repeat: no-repeat !important; tells webkit not to use background repetition eliminating the problem.
As for background-size, the value 100% does the same as the original repeat-x, and the 23px is the height of the image that produces your gradient. in this case is the height of /RichWidgets/img/bar_gradient.png.
When we added this CSS3 style the PDF rendered correctly as shown in the following image:
Gradient problem solved
Best Regards,
Nuno Guedes
Use inline css for this page which convert to pdf.

Why do I need rotateX to make :after :before tooltips work?

I have a table with tool tips invoked from tr:hover and tr:action using :after and :before.
JsFiddle here
EDIT:
If I don't have the position: relative in the td or the rotateX(0) in tr:hover td the tooltips no longer appear...
Why is this required?
CSS
/*Striped background to show transparency */
body{
background-image: linear-gradient(black 10%, transparent 10%);
background-size: auto 10px;
}
/*Base format*/
table {
float: left;
table-layout: auto;
border-collapse: seperate;
border-spacing: 1px 0;
text-align: left;
cursor: default;
}
td {
/*Fix 1 ?????????????????????????????????????????????????????????????*/
position: relative;
/*???????????????????????????????????????????????????????????????????*/
/*Dynamic elements*/
background-image: linear-gradient(to top, #0033CC, #FFFFDB);
opacity: 0.5;
}
/* Header*/
th {
padding-left: 1%; /*not inherited from table*/
width: 50%;
color: #FFFF66;
background-color: #0000CC;
}
tr:active th {
opacity: 0.5;
color: red;
}
/* Tool tip base*/
/*body*/
tr:hover td:last-child:after, tr:active td:last-child:after {
white-space: nowrap;
position: absolute;
left: calc(100% + 6px);
border-radius: 5px;
color: black;
}
/*pointer*/
tr:hover td:last-child:before, tr:active td:last-child:before{
/*make a little arrow beside the tool tip */
content: '';
border: solid;
width: 0; height: 0;
border-color: transparent #cacae1 transparent transparent;
border-width: 6px 6px 6px 0;
bottom: calc(50% - 6px);
left: 100%;
position: absolute;
}
/*Row hover*/
tr:hover td {
/*transform background gradient*/
background: linear-gradient(to top,#4D70DB,#FFFF00);
/*transform opacity for the element*/
opacity: 0.8;
/*Fix 2 ?????????????????????????????????????????????????????????????*/
transform: rotateX(0);
/*???????????????????????????????????????????????????????????????????*/
}
/* adjust tool tip */
tr:hover td:last-child:after {
content: 'Click to SELECT';
box-shadow: 0 0 8px #FFFF00;
background-image: linear-gradient(to top,#4D70DB,#FFFF00);
}
/*Row select*/
tr:active td {
opacity: 1.0;
color: red;
background-image: linear-gradient(to top,#4D70DB,#FF8585);
}
/* adjust tool tip */
tr:active td:last-child:after {
content: 'SELECTED';
background-image: linear-gradient(to top,#4D70DB,#FF8585);
box-shadow: 0 0 8px red;
color: red;
}
HTML
<body>
<table border="0" width="75%" draggable="false">
<tr id="header">
<th><b>COL1</b></th>
<th><b>COL2</b></th>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
</table>
</body>
When an element is positioned absolutely, it is positioned in relation to its containing block, (generally its nearest positioned ancestor). Applying certain values of transform create a new containing block.
This is why (as mentioned in the comments) replacing the transform with position: relative has the same effect. It too creates a containing block, causing your absolute element to position in relation to it.
Using a relatively positioned ancestor is a much more standard practice than applying an unneeded transform when needing to create a new containing block. I suggest you replace your transform with position: relative.

Resources