Table inconsistent behavior for rows left-border - html

I have a table where the user can set a marker on a specific line, the marker is a 5px border at the row's left border.
When I set the border at the first row the table is padded right by a few pixels, but if I set the border in another row and not the first, the table isn't padded.
<table>
<tbody>
<tr class='marked'><td>A</td><td>A</td><td>A</td></tr>
<tr><td>B</td><td>B</td><td>B</td></tr>
<tr><td>C</td><td>C</td><td>C</td></tr>
</tbody>
</table>
<table>
<tbody>
<tr><td>A</td><td>A</td><td>A</td></tr>
<tr class='marked'><td>B</td><td>B</td><td>B</td></tr>
<tr><td>C</td><td>C</td><td>C</td></tr>
</tbody>
</table>
Is this the expected behavior? If it is, how can I fix it? I tested on Firefox and Chrome and both of them behave the same way.
Fiddle: https://jsfiddle.net/2hwuq8ed/

Although I couldn't find any specific documentation to corroborate this, based on what I know of html tables, through practical experience (many hours of building html newsletter templates mostly), the first row can effect the positioning of any row which follows under unique situations such as these. This is due to the nature of tabular formats and could be considered expected behaviour.
Consider offsetting the deficit, created by applying the border property to the first row or cell, by declaring a transparent border of the same width for all cells which are not .marked, e.g:
tr:not(.marked) {
border-left: 5px solid transparent;
}
Updated JSFiddle
table {
border-collapse: collapse;
}
tr {
background-color: blue;
}
tr:nth-child(odd) {
background-color: grey;
}
tr.marked {
border-left: 5px solid green;
}
tr:not(.marked) {
border-left: 5px solid transparent;
}
td:first-child {
width: 100px;
}
td {
width: 50px;
}
<table>
<tbody>
<tr class='marked'><td>A</td><td>A</td><td>A</td></tr>
<tr><td>B</td><td>B</td><td>B</td></tr>
<tr><td>C</td><td>C</td><td>C</td></tr>
</tbody>
</table>
<br>
<table>
<tbody>
<tr><td>A</td><td>A</td><td>A</td></tr>
<tr class='marked'><td>B</td><td>B</td><td>B</td></tr>
<tr><td>C</td><td>C</td><td>C</td></tr>
</tbody>
</table>
If you need to rid tables of that preceding whitespace altogether, consider applying the visual marker to a pseudo-element of the first nested table cell instead, e.g:
tr.marked td:first-child:before {
content: "";
position: absolute;
left: -3px;
top: 0;
bottom: 0;
background: green;
width: 5px;
}
Updated JSFiddle
table {
border-collapse: collapse;
}
tr {
background-color: blue;
}
tr:nth-child(odd) {
background-color: grey;
}
tr.marked td:first-child:before { /* additional */
content: "";
position: absolute;
left: -3px;
top: 0;
bottom: 0;
background: green;
width: 5px;
}
td:first-child {
width: 100px;
position: relative; /* required for absolutely positioned pseudo-elements */
}
td {
width: 50px;
}
<table>
<tbody>
<tr class='marked'><td>A</td><td>A</td><td>A</td></tr>
<tr><td>B</td><td>B</td><td>B</td></tr>
<tr><td>C</td><td>C</td><td>C</td></tr>
</tbody>
</table>
<br>
<table>
<tbody>
<tr><td>A</td><td>A</td><td>A</td></tr>
<tr class='marked'><td>B</td><td>B</td><td>B</td></tr>
<tr><td>C</td><td>C</td><td>C</td></tr>
</tbody>
</table>

Remove border-collapse and add cellspacing="0" cellpadding="0"
td{
border:none
}
tr {
background-color: blue;
}
tr:nth-child(odd) {
background-color: grey;
}
tr.marked {
border-left: 5px solid green;
}
td:first-child {
width: 100px;
}
td {
width: 50px;
}
<table cellspacing="0" cellpadding="0">
<tbody>
<tr class='marked'><td>A</td><td>A</td><td>A</td></tr>
<tr><td>B</td><td>B</td><td>B</td></tr>
<tr><td>C</td><td>C</td><td>C</td></tr>
</tbody>
</table>
<table cellspacing="0" cellpadding="0">
<tbody>
<tr><td>A</td><td>A</td><td>A</td></tr>
<tr class='marked'><td>B</td><td>B</td><td>B</td></tr>
<tr><td>C</td><td>C</td><td>C</td></tr>
</tbody>
</table>

Related

How to set page break on the table with one tr if content of table cell is too big?

I have 4 different tables in my div container. I have trouble fitting my last table on the page. In my last table there is only one table cell. The height on this td cell is set to 200px. I'm wondering if I can set page-break on my last table. Here is example of my table:
<table class="srTable">
<thead>
<tr>
<th>Summary</th>
</tr>
</thead>
<tbody>
<tr>
<td id="summary"></td>
</tr>
</tbody>
</table>
Here is my CSS:
table.srTable {
margin-top: 5px;
margin-bottom: 5px;
width: 100%;
border: 1px solid black;
border-collapse: collapse;
}
table.srTable th {
text-align: center;
border: 1px solid black;
background-color: #E0DBDD;
}
table.srTable td {
height: 180px;
text-align: left;
vertical-align: top;
}
#media print {
table.srTable { page-break-after:auto }
table.srTable tr { page-break-inside:avoid; page-break-after:auto }
table.srTable td { page-break-inside:avoid; page-break-after:auto }
}
If content in srTable can't fit on the page I would like to see entier table on the next page. Code above didn't work, table stayed on the first page and I couldn't see bottom border of my td cell.
You can use a much simpler solution. You only have to set page-break-inside: avoid; on the table.srTable. The other rules for <tr> or <td> aren't needed:
table.srTable {
margin: 5px 0;
width: 100%;
border: 1px solid black;
border-collapse: collapse;
}
table.srTable th {
text-align: center;
border: 1px solid black;
background-color: #E0DBDD;
}
table.srTable td {
height: 180px;
text-align: left;
vertical-align: top;
}
div {
height:98vh;
}
#media print {
table.srTable {
page-break-inside: avoid;
}
}
<div></div>
<table class="srTable">
<thead>
<tr>
<th>Summary</th>
</tr>
</thead>
<tbody>
<tr>
<td id="summary"></td>
</tr>
</tbody>
</table>

Table with border-bottom that is shorter than the full width

I have a table that needs to look like the attached image.
Notice the border under Name that does not extend the full length like the row highlight does. What I can't figure out is how to get the border to be short and the row background to extend to the edge of the containing div. Currently I'm applying padding to the first and last <td> cells to get the padding. My initial attempt was to apply the padding to the <tr> and apply the border to the <th>'s in the table head but it seems <tr>'s do not take padding even with border-collapse: collapse; set.
Here is an attached jsfiddle of the problem. The red border needs to be aligned with the td content.
https://jsfiddle.net/0vhqg4xe
Any ideas would be appreciated.
You can add a <span> tag around each text in <th>, and apply the border to it.
<th><span>Test 1</span></th>
<th><span>Test 2</span></th>
thead th span {
display: block;
border-bottom: 1px solid red;
}
.wrapper {
background: blue;
color: white;
padding-top: 10px;
padding-bottom: 10px;
}
table {
width: 100%;
border-collapse: collapse;
}
th {
text-align: left;
border: 0;
}
tr {
border: 0;
}
thead th span {
display: block;
border-bottom: 1px solid red;
}
tr.highlight {
background: green;
}
tr > td:first-child,
th:first-child {
padding-left: 20px;
}
tr > td:last-child,
th:last-child {
padding-right: 20px;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th><span>Test 1</span>
</th>
<th><span>Test 2</span>
</th>
</tr>
</thead>
<tbody>
<tr class="highlight">
<td>Some Text</td>
<td>Some Text</td>
</tr>
<tr>
<td>Some Text</td>
<td>Some Text</td>
</tr>
<tr>
<td>Some Text</td>
<td>Some Text</td>
</tr>
</tbody>
</table>
</div>
Or, use a pseudo element for the border, so you won't need to change the HTML.
thead tr th {
position: relative;
}
thead tr th:before {
content: "";
display: block;
height: 1px;
overflow: hidden;
background: red;
position: absolute;
left: 20px;
right: 0;
bottom: 0;
}
thead tr th:last-child:before {
left: 0;
right: 20px;
}
.wrapper {
background: blue;
color: white;
padding-top: 10px;
padding-bottom: 10px;
}
table {
width: 100%;
border-collapse: collapse;
}
th {
text-align: left;
border: 0;
}
tr {
border: 0;
}
thead tr th {
position: relative;
}
thead tr th:before {
content: "";
display: block;
height: 1px;
overflow: hidden;
background: red;
position: absolute;
left: 20px;
right: 0;
bottom: 0;
}
thead tr th:last-child:before {
left: 0;
right: 20px;
}
tr.highlight {
background: green;
}
tr > td:first-child,
th:first-child {
padding-left: 20px;
}
tr > td:last-child,
th:last-child {
padding-right: 20px;
}
<div class="wrapper">
<table>
<thead>
<tr>
<th>Test 1</th>
<th>Test 2</th>
</tr>
</thead>
<tbody>
<tr class="highlight">
<td>Some Text</td>
<td>Some Text</td>
</tr>
<tr>
<td>Some Text</td>
<td>Some Text</td>
</tr>
<tr>
<td>Some Text</td>
<td>Some Text</td>
</tr>
</tbody>
</table>
</div>
I've recently solved this problem, incase anybody comes across this post in the future, here it is.
Here is an image of the result ...
... here is the code ...
<style>
* {
font-family: sans-serif;
}
/* table wrapper for continuous border */
.table {
width: 500px;
border: solid 1px rgb(221,221,221);
border-radius: 4px;
overflow: hidden;
text-align: left;
}
/* table border */
.table table {
width: 100%;
border-collapse: collapse; /* removes gap between cells */
}
.table thead th {
font-weight: bold;
background-color: rgb(245,245,245);
border-bottom: solid 1px rgb(221, 221, 221);
}
/* cell padding */
.table th, td {
padding: 10px;
}
/* add row hover */
.table tr:hover td {
background-color: rgb(245,245,245);
}
/* create 1px gap in table for line */
.table tr.line-break td {
position: relative;
top: 1px;
}
/* create the line */
.table tr.line-break td:after {
content: '';
position: absolute;
top: -1px;
left: 0px;
height: 1px;
width: 100%;
background-color: rgb(235,235,235);
}
/* reduce width of line for first and last cells, by cell padding amount */
.table tr.line-break td:first-child:after,
.table tr.line-break td:last-child:after {
width: calc(100% - 10px);
}
/* pull line on first cell to the right */
.table tr.line-break td:first-child:after {
right: 0px;
left: auto;
}
</style>
<div class="table">
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Gender</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Smith</td>
<td>Male</td>
<td>35</td>
</tr>
<tr class="line-break">
<td>Steve</td>
<td>Cook</td>
<td>Male</td>
<td>27</td>
</tr>
<tr>
<td>Susan</td>
<td>Walters</td>
<td>Female</td>
<td>34</td>
</tr>
</tbody>
</table>
</div>
... and here is a link of a CodePen I made for the working solution.
https://codepen.io/latchy/pen/wvwoxXe
The reason the table is wrapped inside a DIV is so that when I push the table row down 1px to allow for the height of the line, the border on the sides is not broken. It also makes it easy to apply a border radius to the table.
Hope this helps someone!
-- Latchy
.border-table .bordered {
position: relative;
background: red;
}
.border-table .bordered:before,
.border-table .bordered:after {
width: 90%;
left: 5%;
height: 1px;
background: blue;
content: '';
position: absolute;
}
.border-table .bordered:before {
top: 0;
}
.border-table .bordered:after {
bottom: 0;
}
<div class="wrapper border-table">
<table>
<thead>
<tr>
<th class="bordered">Test 1</th>
<th class="bordered">Test 2</th>
</tr>
</thead>
<tbody>
<tr class="highlight">
<td>Some Text</td>
<td>Some Text</td>
</tr>
<tr>
<td>Some Text</td>
<td>Some Text</td>
</tr>
<tr>
<td>Some Text</td>
<td>Some Text</td>
</tr>
</tbody>
</table>
</div>
Just add an ::after pseudo element to the tr's and play around with the values (preferably in percentages) so you put the "simulated border" in the desired place.
The following code is just an example of what I've added on the image above (notice that last row can be excluded of having border with :last-of-type):
tbody {
tr {
position: relative;
&::after {
content: '';
position: absolute;
width: 95%;
height: 0.5px;
background-color: #d2d4e1;
left: 2.5%;
bottom: 0;
}
&:last-of-type {
&::after {
content: none;
}
}
}
}

How to expand an image in a table cell on hover (through CSS)

I'm trying to make it so that images in cells in an html table expand when you hover over them. I want this to be universal to all tables on my website. Here's my code so far:
td img {
height: 150px;
}
td img:hover{
height: 175px;
}
This code makes the images appear at their correct height, but nothing hapens when I hover over them. Obviously I'm doing something wrong, but what is it?
Consider defining the width and height of the cells and adjust the image within those parameters. This way the rows don't shift around when you hover -- change table image size on hover
html {
padding: 50px;
}
table {
width: 600px;
padding: 10px;
background: #FFF;
border: 1px solid #BBB;
}
th {
padding: 10px;
}
td {
vertical-align: middle;
text-align: center;
padding: 5px;
border: 1px solid #DDD;
}
td:first-child {
width: 50px;
}
td:last-child {
width: 200px;
height: 200px;
}
td img {
width: 75%;
height: auto;
}
td img:hover{
width: 90%;
height: auto;
}
<table>
<thead>
<th>Image Title</th>
<th>Image</th>
</thead>
<tbody>
<tr>
<td>Image 1</td>
<td><img src="http://www.logoeps.net/wp-content/uploads/2013/06/stackoverflow_logo.jpg" /></td>
</tr>
</tbody>
</table>
you can do it with CSS
td:hover img{
height:175px;
}
you can use jQuery for this also :
$('td img').on('mouseenter',function(){
$(this).css({
'height':'175px'
});
});
* {
margin: 0;
padding: 0;
}
img {
height: 150px;
width: auto
}
td:hover img {
background: red;
height: 200px;
}
<table>
<tr>
<th>Title</th>
<th>Image</th>
</tr>
<tr>
<td>Image Title</td>
<td><img src="https://torange.biz/photofx/5/8/image-profile-picture-beautiful-exotic-flower-5532.jpg" alt=""></td>
</tr>
</table>

CSS: mysterious padding with postion absolute in table-cell

I'm experiencing a weird behaviour when trying to absolute position a div element inside a table-cell. To realise absolute positioning, I use a wrapper div element with position:relative:
HTML
<table>
<colgroup>
<col width="200px"></col>
<col width="300px"></col>
</colgroup>
<thead>
<tr>
<th>Caption 1</th>
<th>Caption 2</th>
</tr>
</thead>
<tbody>
<tr>
<td><div class="wrapper"><div class="abs">abs</div></div></td>
<td>Content 2</td>
</tr>
</tbody>
</table>
CSS
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th, td {
border-bottom: 1px solid black;
padding: 0;
margin: 0;
}
.wrapper {
background-color: green;
position: relative;
width: 100%;
border-top: 1px solid blue;
}
.abs {
position: absolute;
margin: 0px;
padding: 0px;
background-color: red;
}
FIDDLE
As you can see, there is a gap between the wrapper div and the top of the containing table-cell. This gap will vanish if I change the abs element to position:relative.
So where does this gap come from and how do I prevent it?
Since you take .abs out of the normal page flow, .wrapper no longer has any content, so it collapses on itself and all you see is the border along the top of it.
It is in the vertical-middle of the cell because middle is the default vertical-align style for td and ths.
This can be better demonstrated if we add a non-breaking space in the mix:
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th, td {
border-bottom: 1px solid black;
padding: 0;
margin: 0;
}
.wrapper {
background-color: green;
position: relative;
width: 100%;
border-top: 1px solid blue;
}
.abs {
position: absolute;
top:0;
margin: 0px;
padding: 0px;
background-color: red;
}
<table>
<colgroup>
<col width="200px"></col>
<col width="300px"></col>
</colgroup>
<thead>
<tr>
<th>Caption 1</th>
<th>Caption 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="wrapper">
<div class="abs">abs</div>
</div>
</td>
<td>Content 2</td>
</tr>
</tbody>
</table>
You have to set dimensions to wrapper,
.wrapper {height: 30px;}
http://jsfiddle.net/b1j2gbn3/2/
Else, the .wrapper height is 0 and table cell has vertical-align: middle; by default, so the blue border is in the middle of the cell.

Can I shorten the length of a table border? [duplicate]

This question already has answers here:
Border Height on CSS
(12 answers)
Closed 9 years ago.
I have border-right on a table and I would like it to be a few pixels short from the top and bottom, preferably 80-90% height of the <td> as the table won't stay the same.
Like this:
Is this possible to do?
table{
border-right: 1px solid #f00;
}
Fiddle
This isn't possible, as you describe it, as the border of an element extends (by definition) around the full border. You can, however, fake it to some extent using nested elements or with CSS-generated content.
For example, with the following HTML:
<table>
<tbody>
<tr>
<td>text in cell</td>
</tr>
</tbody>
</table>
And the following CSS:
td {
border: 2px solid #000;
/* change the border-color to disguise the presence of the actual border
left as #000 here, to show where the fake 'border' sits in relation to
the actual border-right */
padding: 0.5em;
position: relative;
}
td::after {
content: '';
background-color: #f00;
position: absolute;
left: 100%;
top: 3px;
bottom: 3px;
width: 2px;
}
JS Fiddle demo.
For this to be used in an email client, unfortunately a nested element is required (given the hideously primitive capacities of email clients, even now). So, the following HTML:
<table>
<tbody>
<tr>
<td>text in cell<div></div></td>
</tr>
</tbody>
</table>
And CSS should work:
td {
border: 2px solid #000;
padding: 0.5em;
position: relative;
}
td div {
background-color: #f00;
position: absolute;
left: 100%;
top: 3px;
bottom: 3px;
width: 2px;
}
JS Fiddle demo.
You can do it with a pseudo-element:
table {
position: relative;
}
table:after {
position: absolute;
border-right: 1px solid #f00;
content: "";
top: 5%;
bottom: 5%;
right: -1px;
}
Example: http://jsfiddle.net/hY6Te/11/
Is additional markup acceptable?
Fiddle
<div id="wrapper">
<table width="200" height="100" bgcolor="#eee0e0">
<tr>
<td>TEXT</td>
</tr>
</table>
</div>
table{
border-right: 1px solid #f00;
}
#wrapper {
background: #eee0e0;
padding: 20px 0;
display: table; /* necessary for shirnk wrapping (inline-block would also work)
}