Why border is not visible with "position: sticky" when background-color exists?
CssGoogle ChromeStickyCss Problem Overview
position: 'sticky'
landed in Chrome 56, but it makes the border invisible in certain circumstances.
Consider the following example:
table {
border-collapse: collapse;
}
thead {
position: sticky;
top: 0;
}
th {
background-color: #fff;
border-right: 5px solid red;
}
<table>
<thead>
<tr>
<th>First</th>
<th>Second</th>
<th>Third</th>
</tr>
</thead>
</table>
In Chrome 56.0.2924.76, only the last <th>
's border is visible, and this is only when <th>
has a background-color
specified.
Is this a bug in Chrome?
Css Solutions
Solution 1 - Css
I faced the same problem. My workaround was to use the :after
pseudo element to emulate a bottom border.
th:after{
content:'';
position:absolute;
left: 0;
bottom: 0;
width:100%;
border-bottom: 1px solid rgba(0,0,0,0.12);
}
Solution 2 - Css
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>
background-clip
seems also efficient and harmless:
table {
margin-top: 1em;
border-collapse: collapse;
margin-bottom: 200vh
}
thead {
position: sticky;
top: 0;
}
th {
border-right: 5px solid red;
background:white;
background-clip: padding-box;
}
<table>
<thead>
<tr>
<th>First</th>
<th>Second</th>
<th>Third</th>
</tr>
</thead>
</table>
Solution 3 - Css
if table contains border around columns and we add sticky position, when we scroll the table show overlapping effect to remove this effect and retains border we need to remove border and add outline instead of border
table tr th{
outline: 1px solid #e9ecef;
border:none;
outline-offset: -1px;
}
Solution 4 - Css
I have solved with shadow
table tr th {
position: -webkit-sticky;
position: sticky;
top: -1px;
z-index: 2;
background-color: white;
-moz-box-shadow: 0 0 1px -1px #ccc;
-webkit-box-shadow: 0 0 1px -1px #ccc;
box-shadow: 0 0 1px -1px #ccc;
}
Solution 5 - Css
The next example currently works well under Chrome (65) and Firefox (59).
The SCSS code illustrates better the relationship between values. You can set the desired values by change the variables.
SCSS:
table {
&.sticky-table-head {
// Variables
$border-width: 2px;
$head-background-color: #ded;
$head-border-color: #8a8;
$background-color: #f8fff8;
$border-color: #cdc;
$color: #686;
// Declarations
margin-bottom: 1em;
border-collapse: collapse;
background-color: $background-color;
color: $color;
&:last-child {
margin-bottom: 100vh;
}
th,
td {
border: $border-width solid $border-color;
}
thead {
th {
position: sticky;
top: ($border-width / 2);
background-color: $head-background-color;
outline: $border-width solid $head-border-color;
outline-offset: (- $border-width / 2);
}
}
}
}
HTML and compiled CSS:
table.sticky-table-head {
margin-bottom: 1em;
border-collapse: collapse;
background-color: #f8fff8;
color: #686;
}
table.sticky-table-head:last-child {
margin-bottom: 100vh;
}
table.sticky-table-head th,
table.sticky-table-head td {
border: 2px solid #cdc;
}
table.sticky-table-head thead th {
position: -webkit-sticky;
position: sticky;
top: 1px;
background-color: #ded;
outline: 2px solid #8a8;
outline-offset: -1px;
}
<div>
<!-- First table -->
<table class="sticky-table-head">
<thead>
<tr>
<th>Lorem</th>
<th>Ipsum</th>
<th>Dolor sit amet</th>
</tr>
</thead>
<tbody>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
</tbody>
</table>
<!-- Second table -->
<table class="sticky-table-head">
<thead>
<tr>
<th>Lorem</th>
<th>Ipsum</th>
<th>Dolor sit amet</th>
</tr>
</thead>
<tbody>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
<tr>
<td>ipsum</td>
<td>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</td>
<td>sit</td>
</tr>
</tbody>
</table>
</div>
Solution 6 - Css
Try this instead:
background-clip: padding-box;
Solution 7 - Css
Use ::after
pseudo selector to emulate right border
Example:
th::after {
content: '';
position: absolute;
top: 0;
right: 0;
height: 100%;
border-right: 1px solid #e7e7e7;
}
Solution 8 - Css
thead::after {
content: '';
display: block;
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 1px;
background-color: #333333;
}
I fixed this same problem with a pseudo element instead of a border. Not sure of why this happens in the first place, though.
Solution 9 - Css
I'm using only horizontal borders in my page so this may need to be adapted to your particular case. By using a half-transparent background colour for the table cells, I've discovered that it's the bottom end of the background that overlays the horizontal border. I guess it'll be the same with the right end for the vertical border. To avoid the border overlapping, I've set a linear gradient that fills everything but spares the last pixel. Unfortunately, this only works in Firefox and Chrome but not in Edge.
td:first-child {
position: sticky;
left: 0px;
z-index: 2;
background: linear-gradient(to bottom, white, white calc(100% - 1px),
transparent calc(100% - 1px), transparent);
}
Edge does paint a linear gradient but from white at the top to transparent at the bottom, ignoring the hard change at the stop at 100% - 1px.
Solution 10 - Css
Another option is to wrap your content in an element and put the border on that:
.th-inner {
padding: 10px;
border-bottom: 1px solid #ccc;
}
<th>
<div class="th-inner">your content</div>
</th>
However I found that putting the border on the th
worked without border-collapse: collapse
on the table, so I went for that.
Solution 11 - Css
html {
padding: 0px;
margin: 0px;
}
body {
padding: 0px;
margin: 0px;
width: 100%;
}
th,
td {
padding: 10px;
border: 0.1px solid #e8e0e0;
padding-right: 10px;
}
th {
text-align: center;
background: #f3f3f3;
background-clip: padding-box;
}
thead th:first-child {
left: 0;
z-index: 1;
}
tbody th:first-child {
text-align: center;
position: -webkit-sticky;
/* for Safari */
position: sticky;
left: 0;
}
tbody th,
thead th:first-child {
width: 30px;
min-width: 30px;
max-width: 30px;
word-break: break-all;
}
.fixed_header {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
}
/* fixed header */
thead th {
/* for Safari */
text-align: center;
position: -webkit-sticky;
position: sticky;
top: 0;
}
.fixed_header th,
.fixed_header td {
padding: 10px;
width: 90px;
}
.table_container {
position: relative;
width: 100%;
min-height: 500px;
overflow: auto;
background: cornsilk;
}
<table class="fixed_header">
<thead>
<tr>
<th></th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td>row 1-1</td>
<td>row 1-2</td>
<td>row 1-3</td>
<td>row 1-4</td>
<td>row 1-1</td>
<td>jhhhh-2</td>
<td>row 1-3</td>
<td>row 1-4</td>
<td>row 1-1</td>
<td>row 1-2</td>
<td>row 1-3</td>
<td>row 1-4</td>
<td>row 1-1</td>
<td>row 1-2</td>
<td>row 1-3</td>
<td>row 1-4</td>
<td>row 1-1</td>
<td>row 1-2</td>
<td>row 1-3</td>
<td>row 1-4</td>
</tr>
</tbody>
</table>
</div>
Solution 12 - Css
box-shadow: inset 0 0 0px 2px #555;
instead of border: solid 2px #555;
will work. But that is indeed a bug and should be fixed by the browsers.