Search code examples
htmlcss

How to prevent a sticky table header showing horizontally scrolled content in the border?


I want to prevent the red headers from showing in the blue header's border when scrolling horizontally. I must have a white border in the blue headers.

.container {
  overflow: auto;
  width: 200px;
}

table {
  border-collapse: collapse;
}

th {
  background-color: red;
  border-right: 1px solid white;
  color: white;
  padding: 10px;
  z-index: 1;
}

.sticky {
  background-color: blue;
  position: sticky;
  z-index: 2;
}

.test1 {
  left: 0;
}

.test2 {
  left: 57px;
}

.test3 {
  left: 114px;
}
<div class="container">
  <table>
    <thead>
      <tr>
        <th class="sticky test1">
        Test1
        </th>
        <th class="sticky test2">
        Test2
        </th>
        <th class="sticky test3">
        Test3
        </th>
        <th>
        Test4
        </th>
        <th>
        Test5
        </th>
        <th>
        Test6
        </th>
      </tr>
    </thead>
  </table>
</div>

I want to prevent the red headers from showing in the blue header's border when scrolling horizontally. I must have a white border in the blue headers.


Solution

  • You could remove all borders and use e a CSS pseudo-element on each header cell to fake the border effect...

    Also, would suggest you fix the width of your sticky columns, that way you can set the left property a bit easier. I've gone ahead to use the exact width as I was getting tiny shifts (~1px) when using the horizontal scroll.

    .container {
        overflow-x: auto;
        width: 200px;
    }
    
    table {
        border-collapse: collapse;
    }
    
    th {
        background-color: red;
        color: white;
        padding: 10px;
        position: relative;
    }
    
    .sticky {
        background-color: blue;
        position: sticky;
        z-index: 1;
    }
    
    th::before {
        content: "";
        position: absolute;
        top: 0;
        right: 0;
        width: 2px;
        /* Adjust fake border width here */
        height: 100%;
        background-color: white;
    }
    
    .test1 {
        left: 0;
    }
    
    .test2 {
        left: 55.86px;
        /* this is the exact width of the column header */
    }
    
    .test3 {
        left: calc(55.86px * 2);
        /* made this exact to stop the tiny shifts when scrolling */
    }
    <div class="container">
        <table>
            <thead>
                <tr>
                    <th class="sticky test1">
                        Test1
                    </th>
                    <th class="sticky test2">
                        Test2
                    </th>
                    <th class="sticky test3">
                        Test3
                    </th>
                    <th>
                        Test4
                    </th>
                    <th>
                        Test5
                    </th>
                    <th>
                        Test6
                    </th>
                </tr>
            </thead>
        </table>
    </div>