Table Headers Position:Sticky and Border Issue

Border style do not work with sticky position element

The problem occurs because of the use of border-collapse: collapse. When browsers collapse the borders, the top and bottom border on the <th> must be getting applied to surrounding elements—the top border to the <table> and the bottom border to the following <tr>.

If you use border-collapse: separate and fashion your borders to sit on one side, the borders will truly attach to the <th>, stay fixed as expected, and appear collapsed.

Here are example styles that can be applied to your HTML snippet.

#wrapper {
width: 400px;
height: 200px;
overflow: auto;
}

table {
width: 100%;
text-align: center;
border-collapse: separate; /* Don't collapse */
border-spacing: 0;
}

table th {
/* Apply both top and bottom borders to the <th> */
border-top: 2px solid;
border-bottom: 2px solid;
border-right: 2px solid;
}

table td {
/* For cells, apply the border to one of each side only (right but not left, bottom but not top) */
border-bottom: 2px solid;
border-right: 2px solid;
}

table th:first-child,
table td:first-child {
/* Apply a left border on the first <td> or <th> in a row */
border-left: 2px solid;
}

table thead th {
position: sticky;
top: 0;
background-color: #edecec;
}

Table headers position:sticky and border issue

You can add

.table {
border-collapse: separate;
}

But unfortunately it looks bad, a better solution will be adding a workaround using a pseudo-element.

th:after,
th:before {
content: '';
position: absolute;
left: 0;
width: 100%;
}

th:before {
top: -1px;
border-top: 1px solid red;
}

th:after {
bottom: -1px;
border-bottom: 2px solid red;
}

.table-sticky-container {
height: 200px;
overflow-y: scroll;
border-top: 1px solid green;
border-bottom: 1px solid green;
}

.table-sticky th {
position: -webkit-sticky;
position: sticky;
top: 0;
z-index: 2;
}

th:after,
th:before {
content: '';
position: absolute;
left: 0;
width: 100%;
}

th:before {
top: -1px;
border-top: 1px solid red;
}

th:after {
bottom: -1px;
border-bottom: 2px solid red;
}
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css'>

<div class="table-sticky-container">
<table class="table table-sticky">
<thead class="thead-light">
<tr>
<th scope="col">Name</th>
<th scope="col">Title</th>
<th scope="col">ID</th>
<th scope="col">Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>Malcolm Reynolds</td>
<td>Captain</td>
<td>9035749867</td>
<td>mreynolds</td>
</tr>
<tr>
<td>Zoe Washburne</td>
<td>First Officer</td>
<td>8908980980</td>
<td>zwashburne</td>
</tr>
<tr>
<td>Kaylee Frye</td>
<td>Engineer</td>
<td>6678687678</td>
<td>kfrye</td>
</tr>
<tr>
<td>Malcolm Reynolds</td>
<td>Captain</td>
<td>9035749867</td>
<td>mreynolds</td>
</tr>
<tr>
<td>Zoe Washburne</td>
<td>First Officer</td>
<td>8908980980</td>
<td>zwashburne</td>
</tr>
<tr>
<td>Kaylee Frye</td>
<td>Engineer</td>
<td>6678687678</td>
<td>kfrye</td>
</tr>
</tbody>
</table>
</div>

HTML Table with Border Radius & Sticky Header

As Ivan suggested it seems that using pseudo elements for covering unwanted borders below header is (surprisingly) the only viable option. I'd advise using pseudos not only for covering "outer" area but even for drawing the arcs and filling the "inner" area. It is possible to do so using stacked backgrounds. Applied to original code:

/* 
§ Additions / Changes
*/
table thead th {
position: relative;
}

/* Pseudos exceeding header boundary by border width; with rectangle covering half circle and rest of height */

table thead th:last-child::after,
table thead th:first-child::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: calc(-1 * var(--global-border-width-1));
width: var(--global-border-radius);
background-image:
linear-gradient(to bottom,
transparent var(--global-border-radius),
var(--global-title-color) 0),
radial-gradient(circle at var(--global-border-radius) var(--global-border-radius),
var(--global-title-color) var(--global-border-radius),
var(--global-content-background-color) 0);
background-position: top left;
background-size:
var(--global-border-diameter) 100%,
var(--global-border-diameter) var(--global-border-diameter);
background-repeat: no-repeat;
}

table thead th:last-child::after {
left: auto;
right: calc(-1 * var(--global-border-width-1));
background-position: top right;
}

/*
§ Declarations and original style
*/

html {
--global-content-background-color: white;
--global-title-color: black;
--global-background-color: lightblue;
--global-border-color: black;
--global-border-radius: 20px;
--global-border-width-1: 10px;
--global-space-fixed-2: 10px;
--global-space-fixed-3: 15px;
--global-border-diameter: calc(2 * var(--global-border-radius));
background-color: var(--global-content-background-color);
}

table {
color: var(--global-title-color);
background-color: var(--global-content-background-color);
border-collapse: separate;
border-color: var(--global-title-color);
border-style: solid;
border-radius: var(--global-border-radius);
border-width: 0 var(--global-border-width-1) var(--global-border-width-1) var(--global-border-width-1);
border-spacing: 0;
width: 100%;
}

table thead {
position: sticky;
top: 0;
z-index: 10;
}

table thead th {
color: var(--global-background-color);
background-color: var(--global-title-color);
padding: var(--global-space-fixed-2) var(--global-space-fixed-3);
vertical-align: bottom;
}

table tbody td {
border-top: var(--global-border-width-1) solid var(--global-border-color);
padding: var(--global-space-fixed-2) var(--global-space-fixed-3);
vertical-align: top;
}

table tbody tr:last-child td:first-child {
border-bottom-left-radius: var(--global-border-radius);
}

table tbody tr:last-child td:last-child {
border-bottom-right-radius: var(--global-border-radius);
}

/*
§ Unrelated / demo
*/

* {
scroll-margin-top: calc(var(--global-space-fixed-2) * 4 + 1rem);
/* = height of sticky thead + top padding of cell, provided text in thead does not wrap */
scroll-margin-bottom: 1em;
}

td {
height: 60vh;
}

td a {
float: right
}

tr:last-child td {
vertical-align: bottom;
}

a[name]:empty::before {
content: attr(name);
}

th:not(#\0):hover::before {
background-image: linear-gradient(to bottom, transparent var(--global-border-radius), #0F08 0), radial-gradient(circle at center, #00F8 var(--global-border-radius), #F2F4 0);
background-position: top left;
background-size: var(--global-border-diameter) 100%, var(--global-border-diameter) var(--global-border-diameter);
}
<table>
<thead>
<tr>
<th>Fake non-transparent "border-radius"</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a href="#⬆️" name="⬇️"></a> For fixed header</td>
</tr>
<tr>
<td>
<a href="#⬇️" name="⬆️"></a> Using CSS stacked background images in pseudo elements</td>
</tr>
</tbody>
</table>

Why border is not visible with position: sticky when background-color exists?

seems like to force a reflow will partially help :

table {

border-collapse: collapse;

}

thead {

position: sticky;

top: 0;

}

th {

border-right: 5px solid red;

transform:scale(0.999);

}
  <table>

<thead>

<tr>

<th>First</th>

<th>Second</th>

<th>Third</th>

</tr>

</thead>

</table>

Make sticky table header row completely opaque

You can set a shadow around the th elements, it will do the job.

I have set it to yellow to make it more visible, of course you can set it to white

.table-wrapper {
height: 90px;
overflow: scroll;
}

table {
border-collapse: separate;
border-spacing: 10px;
}

td,
th {
width: 50px;
}

th {
background-color: #00aeef;
border-radius: 5px;
box-shadow: 10px -6px 0px 6px yellow, -4px -6px 0px 6px yellow;
}

td {
border-radius: 5px;
border: 5px solid black;
}

thead>tr>th {
top: 0;
position: sticky;
}
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Col1</th>
<th>Col2</th>
<th>Col3</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
<th>Col7</th>
<th>Col8</th>
<th>Col9</th>
</tr>
</thead>
<tbody>
<tr>
<td>Col1</td>
<td>Col2</td>
<td>Col3</td>
<td>Col4</td>
<td>Col5</td>
<td>Col6</td>
<td>Col7</td>
<td>Col8</td>
<td>Col9</td>
</tr>
<tr>
<td>Col1</td>
<td>Col2</td>
<td>Col3</td>
<td>Col4</td>
<td>Col5</td>
<td>Col6</td>
<td>Col7</td>
<td>Col8</td>
<td>Col9</td>
</tr>
<tr>
<td>Col1</td>
<td>Col2</td>
<td>Col3</td>
<td>Col4</td>
<td>Col5</td>
<td>Col6</td>
<td>Col7</td>
<td>Col8</td>
<td>Col9</td>
</tr>
</tbody>
</table>
</div>

Sticky td of table is covering the sticky header th . and td border get disappered on scroll. How to resolve this?

Use z-index for the th elements and consider background to replace the border for the left elements

Check comments in the below code:

.tableFixHead {

overflow-y: auto;

max-height: 300px;

margin-left: -15px;

margin-right: -15px;

margin-bottom: 100px;

}

.tableFixHead thead th {

position: sticky;

top: 0;

z-index:1; /* added */

}

/* Borders */

.tableFixHead,

.tableFixHead td {

box-shadow: inset 1px -1px #293033;

}

.tableFixHead th {

box-shadow: inset 1px 1px #293033, 0 1px #293033;

}

table {

border-spacing: 0;

}

th {

padding: 8px;

color: #e9ecef;

background-color: #1e2324;

font-weight: 500;

font-size: 14px;

}

thead {

text-align: center;

}

td {

background-color: #041230;

text-align: center;

padding: 10px;

color: #e9ecef;

min-width: 150px;

font-size: 13px;

word-spacing: 2px;

}

td:nth-child(1) {

min-width: 50px;

max-width: 50px;

font-weight: bold;

color: #66FCF1;

/* added */

background:

linear-gradient(#041230,#041230) center/calc(100% - 2px) calc(100% - 2px) no-repeat,

red;

/**/

position: sticky;

left: 0;

}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">

<div class="container">

<div class="tableFixHead">

<table class="tablecolor2">

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

</tr>

</thead>

<tbody>

<tr>

<td>row 1, cell 1</td>

<td>row 1, cell 2</td>

<td>row 1, cell 3</td>

<td>row 1, cell 4</td>

<td>row 1, cell 5</td>

<td>row 1, cell 6</td>

<td>row 1, cell 7</td>

<td>row 1, cell 8</td>

</tr>

<tr>

<td>row 2, cell 1</td>

<td>row 2, cell 2</td>

<td>row 2, cell 3</td>

<td>row 2, cell 4</td>

<td>row 2, cell 5</td>

<td>row 2, cell 6</td>

<td>row 2, cell 7</td>

<td>row 2, cell 8</td>

</tr>

<tr>

<td>row 3, cell 1</td>

<td>row 3, cell 2</td>

<td>row 3, cell 3</td>

<td>row 3, cell 4</td>

<td>row 3, cell 5</td>

<td>row 3, cell 6</td>

<td>row 3, cell 7</td>

<td>row 3, cell 8</td>

</tr>

<tr>

<td>row 4, cell 1</td>

<td>row 4, cell 2</td>

<td>row 4, cell 3</td>

<td>row 4, cell 4</td>

<td>row 4, cell 5</td>

<td>row 4, cell 6</td>

<td>row 4, cell 7</td>

<td>row 4, cell 8</td>

</tr>

<tr>

<td>row 1, cell 1</td>

<td>row 1, cell 2</td>

<td>row 1, cell 3</td>

<td>row 1, cell 4</td>

<td>row 1, cell 5</td>

<td>row 1, cell 6</td>

<td>row 1, cell 7</td>

<td>row 1, cell 8</td>

</tr>

<tr>

<td>row 2, cell 1</td>

<td>row 2, cell 2</td>

<td>row 2, cell 3</td>

<td>row 2, cell 4</td>

<td>row 2, cell 5</td>

<td>row 2, cell 6</td>

<td>row 2, cell 7</td>

<td>row 2, cell 8</td>

</tr>

<tr>

<td>row 3, cell 1</td>

<td>row 3, cell 2</td>

<td>row 3, cell 3</td>

<td>row 3, cell 4</td>

<td>row 3, cell 5</td>

<td>row 3, cell 6</td>

<td>row 3, cell 7</td>

<td>row 3, cell 8</td>

</tr>

<tr>

<td>row 4, cell 1</td>

<td>row 4, cell 2</td>

<td>row 4, cell 3</td>

<td>row 4, cell 4</td>

<td>row 4, cell 5</td>

<td>row 4, cell 6</td>

<td>row 4, cell 7</td>

<td>row 4, cell 8</td>

</tr>

<tr>

<td>row 1, cell 1</td>

<td>row 1, cell 2</td>

<td>row 1, cell 3</td>

<td>row 1, cell 4</td>

<td>row 1, cell 5</td>

<td>row 1, cell 6</td>

<td>row 1, cell 7</td>

<td>row 1, cell 8</td>

</tr>

<tr>

<td>row 2, cell 1</td>

<td>row 2, cell 2</td>

<td>row 2, cell 3</td>

<td>row 2, cell 4</td>

<td>row 2, cell 5</td>

<td>row 2, cell 6</td>

<td>row 2, cell 7</td>

<td>row 2, cell 8</td>

</tr>

<tr>

<td>row 3, cell 1</td>

<td>row 3, cell 2</td>

<td>row 3, cell 3</td>

<td>row 3, cell 4</td>

<td>row 3, cell 5</td>

<td>row 3, cell 6</td>

<td>row 3, cell 7</td>

<td>row 3, cell 8</td>

</tr>

<tr>

<td>row 4, cell 1</td>

<td>row 4, cell 2</td>

<td>row 4, cell 3</td>

<td>row 4, cell 4</td>

<td>row 4, cell 5</td>

<td>row 4, cell 6</td>

<td>row 4, cell 7</td>

<td>row 4, cell 8</td>

</tr>

<tr>

<td>row 1, cell 1</td>

<td>row 1, cell 2</td>

<td>row 1, cell 3</td>

<td>row 1, cell 4</td>

<td>row 1, cell 5</td>

<td>row 1, cell 6</td>

<td>row 1, cell 7</td>

<td>row 1, cell 8</td>

</tr>

<tr>

<td>row 2, cell 1</td>

<td>row 2, cell 2</td>

<td>row 2, cell 3</td>

<td>row 2, cell 4</td>

<td>row 2, cell 5</td>

<td>row 2, cell 6</td>

<td>row 2, cell 7</td>

<td>row 2, cell 8</td>

</tr>

<tr>

<td>row 3, cell 1</td>

<td>row 3, cell 2</td>

<td>row 3, cell 3</td>

<td>row 3, cell 4</td>

<td>row 3, cell 5</td>

<td>row 3, cell 6</td>

<td>row 3, cell 7</td>

<td>row 3, cell 8</td>

</tr>

<tr>

<td>row 4, cell 1</td>

<td>row 4, cell 2</td>

<td>row 4, cell 3</td>

<td>row 4, cell 4</td>

<td>row 4, cell 5</td>

<td>row 4, cell 6</td>

<td>row 4, cell 7</td>

<td>row 4, cell 8</td>

</tr>

</tbody>

</table>

</div>

<!-- Table Dormant / Discontinued -->

</div>

<!-- container -->

</body>


Related Topics



Leave a reply



Submit