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
How to Indent Multiple Levels of Select Optgroup with CSS
CSS Text Underlining Too Long When Letter-Spacing Is Applied
Responsive Image Align Center Bootstrap 3
Three Divs Side by Side with Spacing in Between
Table with Fixed Header at Top
What CSS Should I Use to Get a Border Around an Option Tag in Both Firefox and Ie
How to Autogrow a Textarea with CSS
Why Alignment Mark List Is Different on Webkit When Using :Before Height
Why Does an Inline-Block Align to Top If It Has No Content
Remove Value Attribute of Input Element Using CSS Only
Internet Explorer 11 Word Wrap Is Not Working
Cross-Browser Embedded Font in Svg Image
How to Do Tag Wrapping in VS Code
Customise Ng Bootstrap Carousel in Angular
Fixed Positioned Header Persists on Desktop But Not on Mobile
Internet Explorer Doesn't Recognise the 'Html' CSS Background Image Tag
CSS Remove Default Blue Border
How to Draw Multiple Horizontal Lines (Notebook Paper Effect) Using CSS