The left side of the table I need a margin on the left of the tr but the line under the heading needs to go to the edge of the table. When scrolling left/right I need the table to go under the margin
I have done it in my example by positioning a 20px width div above and below the line.
I’m sure there must be a better way but I’m stuck how I should do it.
If I could but margins on the cells I think it would be easy
Is there a clever way maybe to position a line under the thead thats not actually part of the table
One way to do it would be to have an empty cell on each row and remove the borders from the empty cells in the body. As mentioned before its best not to style the tr but instead style the td and th elements instead as they have better support (note borders on the tr are only available in the collapsing border model but older browsers like IE7 don’t apply them at all).
However your absolute overlay fix seems less code although it relies a bit on magic numbers to make it work.
Here’s another version that applies <tr>{border-bottom}s that might work for you. Please copy the “working page” to a file and open it in your browser to see how it behaves. Do not copy and paste the code into your existing code without understanding it. I am infamous for changing classnames and stuff ()
I recommend testing in Firefox with Zoom Text-Only set in the preferences to see how the page behaves if the user has a different font/font-size - which is likely because of the different devices on the market.
Hi Ron, the red line is not working in Chrome. I haven’t had a look to see why yet as I am in the middle of decoration and covered in paint I’m sure you can work it out anyway.
Thank you, @PaulOB. That is embarrassingly bad code. I didn’t think it should work, but it seemed to so I went with it. Thought I had tested in Chrome, too, but obviously didn’t. I have to chalk it up to a “senior moment”.
Here the border-bottom is correctly assigned to the table-cells. Tested in FF and Chrome. Not tested in IE11 or Edge.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="css/stylesheet.css">
<title>th border-bottom + overshoot</title>
<!--
https://www.sitepoint.com/community/t/table-cell-margins/295230
RachelR
ref: https://codepen.io/mt-ttmt/pen/GdoQgm
-->
<style>
html {
box-sizing:border-box;
padding:0;
margin:0;
}
*,*::before,*::after {
box-sizing:inherit;
}
body {
background-color:gray;
font-family:sans-serif;
}
.page {
background-color:white;
max-width:94em; /* as desired, possibly unnecessary - depends on page design */
margin:0 auto;
}
.tablewrap {
overflow:scroll;
padding:0 .75em;
}
table {
border-collapse:collapse;
width:91.5em;
}
tr:nth-child(even) {
background-color:yellow;
}
th,td {
text-align:left;
padding:.75em .5em;
}
td {
border-bottom:1px solid #aaa;
}
th {
position:relative;
}
th::after {
content:"";
border-bottom:1px solid #f00;
position:absolute;
left:-.75em; /* this offsets the .tablewrap {padding left and right .75em} */
right:-.75em; /* it does not matter that the line is being extended left and right. */
bottom:0;
}
</style>
</head>
<body>
<div class="page">
<div class="tablewrap">
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 5</th>
<th>Header 6</th>
<th>Header 7</th>
<th>Header 8</th>
<th>Header 9</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data - 1256</td>
<td>Data - 1256 Data - 1256 Data - 1256</td>
<td>Data - 1256</td>
<td>1256</td>
<td>125</td>
<td>Data - abc</td>
<td>abc</td>
<td>abc</td>
<td>ABCDE</td>
</tr>
<tr>
<td>Data - 1256</td>
<td>Data - 1256 Data - 1256 Data - 1256</td>
<td>Data - 1256</td>
<td>1256</td>
<td>125</td>
<td>Data - abc</td>
<td>abc</td>
<td>abc</td>
<td>ABCDE</td>
</tr>
<tr>
<td>Data - 1256</td>
<td>Data - 1256 Data - 1256 Data - 1256</td>
<td>Data - 1256</td>
<td>1256</td>
<td>125</td>
<td>Data - abc</td>
<td>abc</td>
<td>abc</td>
<td>ABCDE</td>
</tr>
<tr>
<td>Data - 1256</td>
<td>Data - 1256 Data - 1256 Data - 1256</td>
<td>Data - 1256</td>
<td>1256</td>
<td>125</td>
<td>Data - abc</td>
<td>abc</td>
<td>abc</td>
<td>ABCDE</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
What I gather from Rachel’s codepen is that she wants the margin on the left to remain visible as the table scrolls. However, I could be wrong with that assumption, but that’s what the codepen demonstrates.
If that space is needed to stay visible that’s where things begin to get sticky.
That screenshot above uses border-left on the wrapper in place of padding, but then the pseudo border gets clipped off as it enters an overflow box.
She resolved that by using the empty .table-header div with height:35px; , but as Paul mentioned it was a magic number. Since it has no relationship to the table the border will get misplaced should any of the header text wrap to a new line.
If there’s a challenge in this, it would be to keep that border extension in relation to the table while keeping the margin space in view at all times. That most certainly will require some extra elements as far as I can tell.
My previous example forfeited the left margin in favor of allowing the red line to adapt to the height of the row of <th> elements. Yes, the CSS for the .page and .tablewrap elements could have been combined and one of the elements eliminated; but I have been working on this from different perspectives and didn’t think to combine them.
To me, keeping the left margin in the picture isn’t hard. But if I keep that margin, then I have been unable to allow the vertical position of the red line to adapt to changes in the height of the row of <th> elements using CSS without adding elements.
Positioning the red line could be done with a little JS that monitors the height of the <th> cells and transfers that height to the red line. It could also be done with CSS and a bundle of added HTML elements, but I don’t want to go there.
In defence of the “magic number” (in this case), I am not so sure that being concerned about changes in height of <th> cells is a major problem. Why? Because the table has a fixed width. As the window width narrows, the table scrolls horizontally, it doesn’t compress to fit the window. However, it does seem possible that a user with a different font might experience a probem and it would certainly be better if no one had to adjust that magic number if the contents of the header cells change frequently.
In the following dev example, the left margin works as requested by the OP. I have coded two pseudo-elements that draw one red and one blue line. The blue example uses a magic number. You can selectively uncomment either one or both for testing purposes. I didn’t understand the purpose of the white space to the of the vertical scrollbar so I omitted it. To add it, just add .page {padding-right:.75em} or equivalent.
Slice and dice:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="css/stylesheet.css">
<title>th border-bottom + overshoot2</title>
<!--
https://www.sitepoint.com/community/t/table-cell-margins/295230
RachelR
ref: https://codepen.io/mt-ttmt/pen/GdoQgm
-->
<style>
html {
box-sizing:border-box;
padding:0;
margin:0;
}
*,*::before,*::after {
box-sizing:inherit;
}
body {
background-color:gray;
font-family:sans-serif;
}
.page {
background-color:#fff;
max-width:94em; /* as desired, possibly unnecessary - depends on page design */
position:relative;
padding-left:.75em;
margin:0 auto;
}
/* THE THIN BLUE LINE. One could set top: a fixed em distance from the top (as shown here). The result will be satisfactory at different font sizes. */
.page::before {
content:"";
border-bottom:1px solid #00f;
position:absolute;
left:0;
right:0;
top:2.6875em;
}
/* THE THIN RED LINE. Using eigher of these techniques, the height of the header cells cannot be allowed to change - contents cannot un/wrap.
.page::after {
content:"COMMANDER DATA REPORTING FOR DUTY, SIR";
color:transparent;
padding:.75em .5em;
border-bottom:1px solid #f00;
position:absolute;
left:0;
right:0;
top:0;
}
*/
.tablewrap {
overflow:scroll;
}
table {
border-collapse:collapse;
width:92em;
}
tr:nth-child(even) {
background-color:yellow;
}
th,td {
text-align:left;
padding:.75em .5em;
}
td {
border-bottom:1px solid #aaa;
}
</style>
</head>
<body>
<div class="page">
<div class="tablewrap">
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 5</th>
<th>Header 6</th>
<th>Header 7</th>
<th>Header 8</th>
<th>Header 9</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data - 1256</td>
<td>Data - 1256 Data - 1256 Data - 1256</td>
<td>Data - 1256</td>
<td>1256</td>
<td>125</td>
<td>Data - abc</td>
<td>abc</td>
<td>abc</td>
<td>ABCDE</td>
</tr>
<tr>
<td>Data - 1256</td>
<td>Data - 1256 Data - 1256 Data - 1256</td>
<td>Data - 1256</td>
<td>1256</td>
<td>125</td>
<td>Data - abc</td>
<td>abc</td>
<td>abc</td>
<td>ABCDE</td>
</tr>
<tr>
<td>Data - 1256</td>
<td>Data - 1256 Data - 1256 Data - 1256</td>
<td>Data - 1256</td>
<td>1256</td>
<td>125</td>
<td>Data - abc</td>
<td>abc</td>
<td>abc</td>
<td>ABCDE</td>
</tr>
<tr>
<td>Data - 1256</td>
<td>Data - 1256 Data - 1256 Data - 1256</td>
<td>Data - 1256</td>
<td>1256</td>
<td>125</td>
<td>Data - abc</td>
<td>abc</td>
<td>abc</td>
<td>ABCDE</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
An extra div or two is not always a bad thing, as you know. I was working from a different perspective too and ran through several different versions until I’ve beat it to death. In the end now (I’m done with it) I do believe the extra divs will be the way to go.
If I was needing this table, and knowing what I know now after all the methods I went through. The position of that little red line (1px x 15px) would get it’s height pulled from JS. I also wrote a version with empty cells and it works great but I just wouldn’t go down that road either.
It was a good exercise for me as I discovered some position sticky problems concerning side effects with borders. The workaround for that was the best thing I learned from this. So let’s take a look at that demo.
position:sticky works on ‘thead’ and ‘thead tr’ in FF, but not Chrome
Style the ‘thead th’ for x-browser position: sticky; consistancy
border-collapse: collapse; introduces the problems below
When using bottom border on ‘thead th’ FF will hide 1px
So if bottom border is only 1px it will not show up in FF
Bottom border scrolls away in both FF and Chrome
Solution to those problems can be a linear-gradient with built in border
background: linear-gradient(to top,red, red 1px, #ffff00 1px, #ffff00 100%);
border:none;
If you untick the comments for that gradient and border rule you will see it work.
Here is the version with the extra inner div and padding on the page wrapper along with some JS to find the height for the border-splicing div. I don’t know if JS can style a pseudo element so I used another div for that faux border.
And the empty cells that worked good, but now we have several empty elements that are no better than a couple of extra divs.
Yes I ran into those issues before and used the th elements instead. The tfoot element was also troublesome as safari and ios need the tfoot to be sticky also.
Note that you still need the prefix for IOS and Safari i.e. position:-webkit-sticky;