Table cell margins?

I have a codepen here - https://codepen.io/mt-ttmt/pen/GdoQgm

I thought this would be easy but I’m stuck

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

body{
  background: grey;
  font-family: sans-serif;
}
.page{
  background: white;
  width: 1200px;
  margin: 0 auto;
}
.table-con{
  overflow: scroll;
  max-width: 1200px;
}

.white-block{
  width: 10px;
  height: 150px;
  background: white;
  position: absolute;
  top: 50px;
}

.white-block-1{
  height: 20px;
  top: 20px;
}


table{
  /*table-layout: fixed;*/
  border-collapse: collapse; 
  width: 1500px;
}

thead th{
  text-align: left;
}

thead tr{
  border-bottom: 1px solid #444;
}

tbody tr{
  border-bottom: 1px solid #aaa;
}

tbody tr:nth-child(even){
  background: yellow;
}

th, td{
  padding: 10px 5px;

   &:first-of-type{
    padding-left: 20px;
  }

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.:slight_smile:

2 Likes

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 (:eek:)

<!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 row underline 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 {
   border-bottom:1px solid #aaa;
   text-align:left;
   padding:.75em .5em;
}
thead tr {
   position:relative;
}
thead tr::after {
   content:"";
   border-bottom:1px solid #f00;
   position:absolute;
   left:-.75em;  /* this offsets the .tablewrap {padding left and right .75em} */
   right:-.75em;
   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>

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.

I believe you want this:


table {
	margin:20px auto;
	empty-cells:show; /* Change to "hide" if you prefer*/
	border-collapse:separate;
	border-spacing:0px;
	}
th {
	padding:5px; 
	border-bottom:#000 1px solid;
	text-align:center;
	}
td {
	padding:5px; 
	text-align:center;
	}
td:first-child {
	border-left:#FFF 15px solid;
	}
td:last-child {
	border-right:#FFF 15px solid;
	}

PS: I didn’t change your html code so I thought to avoid to put it here again for nothing.

PS2: Of course you can change whatever your want; background colors, border colors etc…

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 :slight_smile: I’m sure you can work it out anyway.

2 Likes

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>
1 Like

Ron, you could eliminate the .tablewrap div in your example by merging those styles with the wrapping div.

.page {
   background-color:white;
   width: 98%;
   max-width:1200px;  /* as desired, possibly unnecessary - depends on page design */
   margin:0 auto;
   /*.tablewrap*/
   overflow:scroll;
   padding:0 .75em;
}

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.

.page {
   background-color:white;
   width: 98%;
   max-width:1200px;  /* as desired, possibly unnecessary - depends on page design */
   margin:0 auto;
   /*.tablewrap*/
   overflow:scroll;
   /*padding:0 .75em;*/
   border-left: .75em solid #fff;
}

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. :slight_smile:

2 Likes

It’s good to have our heads together on this one.

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>
1 Like

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.

  1. position:sticky works on ‘thead’ and ‘thead tr’ in FF, but not Chrome
  2. Style the ‘thead th’ for x-browser position: sticky; consistancy
  3. border-collapse: collapse; introduces the problems below
  4. When using bottom border on ‘thead th’ FF will hide 1px
  5. So if bottom border is only 1px it will not show up in FF
  6. Bottom border scrolls away in both FF and Chrome
  7. 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.

https://codepen.io/Ray-H/pen/erzZPa

2 Likes

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;

2 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.