Border style do not work with sticky position element

position: sticky border-collapse
position: sticky; bottom
thead sticky
position: sticky not working
css sticky table header
mat-header-row sticky not working
css border-collapse
position: sticky not working with overflow:scroll

I don't know why my border style do not work with position: sticky; attribute. I would like to set border styles on my sticky table header. But I don't want to use the transparent background colour. How can I achieve it? Here are sample codes for my problem and JSFiddle Link

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

table {
  width: 100%;
  text-align: center;
  border-collapse: collapse;
}

table tr th,
table tr td {
  border: 2px solid;
}

table thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  background-color: #edecec;
}
<div id="wrapper">
  <table>
    <thead>
      <tr>
        <th>A</th>
        <th>B</th>
        <th>C</th>
        <th>D</th>
        <th>E</th>
      </tr>
    </thead>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
    </tr>
    <tr>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
    </tr>
    <tr>
      <td>4</td>
      <td>4</td>
      <td>4</td>
      <td>4</td>
      <td>4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>5</td>
      <td>5</td>
      <td>5</td>
      <td>5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>6</td>
      <td>6</td>
      <td>6</td>
      <td>6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>7</td>
      <td>7</td>
      <td>7</td>
      <td>7</td>
    </tr>
    <tr>
      <td>8</td>
      <td>8</td>
      <td>8</td>
      <td>8</td>
      <td>8</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tbody>
    </tbody>
  </table>
</div>

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 th:after, th:before { content: ''; position: absolute; left: 0; width: 100​%; } .table-sticky-container { height: 200px; overflow-y: scroll; border-top: 1px solid <div class="table-sticky-container"> <table class="table table-sticky"> Another working solution (tested at latest Chrome and FF) - wrap  Help CSS position sticky doesn’t work [SOLVED] 2017/06/29 2017/07/01 dinbror Frontend Position sticky isn’t a new thing, but the support is now so great that I started to use it, so what’s position sticky?

You need to use box-shadow property instead of border-top/border-bottom. Additionally you need to delete top/bottom borders for thead and first row of table.

#wrapper {
                width : 400px;
                height : 200px;
                overflow : auto;
            }
            table {
                width : 100%;
                text-align : center;
                border-collapse : collapse;
            }
            table tr th, table tr td {
                border : 2px solid;
            }
            table thead th {
                position: -webkit-sticky;
                position : sticky;
                top : 0;
                background-color : #edecec;
            }
            /* here is the trick */
            table tbody:nth-of-type(1) tr:nth-of-type(1) td {
                border-top: none !important;
            }
            table thead th {
                border-top: none !important;
                border-bottom: none !important;
                box-shadow: inset 0 2px 0 #000000,
                            inset 0 -2px 0 #000000;
                padding: 2px 0;
            }            
<body>
        <div id="wrapper">
            <table>
                <thead>
                    <tr>
                        <th>A</th>
                        <th>B</th>
                        <th>C</th>
                        <th>D</th>
                        <th>E</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>1</td>
                        <td>1</td>
                        <td>1</td>
                        <td>1</td>
                        <td>1</td>
                    </tr>
                    <tr>
                        <td>2</td>
                        <td>2</td>
                        <td>2</td>
                        <td>2</td>
                        <td>2</td>
                    </tr>
                    <tr>
                        <td>3</td>
                        <td>3</td>
                        <td>3</td>
                        <td>3</td>
                        <td>3</td>
                    </tr>
                    <tr>
                        <td>4</td>
                        <td>4</td>
                        <td>4</td>
                        <td>4</td>
                        <td>4</td>
                    </tr>
                    <tr>
                        <td>5</td>
                        <td>5</td>
                        <td>5</td>
                        <td>5</td>
                        <td>5</td>
                    </tr>
                    <tr>
                        <td>6</td>
                        <td>6</td>
                        <td>6</td>
                        <td>6</td>
                        <td>6</td>
                    </tr>
                    <tr>
                        <td>7</td>
                        <td>7</td>
                        <td>7</td>
                        <td>7</td>
                        <td>7</td>
                    </tr>
                    <tr>
                        <td>8</td>
                        <td>8</td>
                        <td>8</td>
                        <td>8</td>
                        <td>8</td>
                    </tr>   
                    <tr>
                        <td>9</td>
                        <td>9</td>
                        <td>9</td>
                        <td>9</td>
                        <td>9</td>
                    </tr>               
                </tbody>
            </table>
        </div>
    </body>

[css-position] Sticky table header, Major browsers have implemented position:sticky for table headers in a I am not sure what should be fixed: my css (some I suppose position:sticky was implemented to ease styling cases like sticky table headers so I believe borders should be a working code: just add background-clip:padding-box; There’s a new value in town for the CSS position property: sticky.It allows us to make elements stick when the scroll reaches a certain point. An element with position: sticky will behave like a relatively-positioned element until it reaches a specified point and then starts behaving like a statically-positioned element.

Because sticky positioning fluctuates between relative and fixed, the only way I can think to circumvent this out-of-box would be take advantage of psuedo classes.

I'm sure there's a more elegant manner to accomplish this but I would just alter the :after and :before psuedo classes to provide the border with absolute positioning.

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

table {
  width: 100%;
  text-align: center;
  border-collapse: collapse;
}

table tr th,
table tr td {
  border: 2px solid;
}

table thead th {
  position: -webkit-sticky;
  position: sticky;
  top: -1px;
  background-color: #edecec;
}
th:after,
th:before {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
}
th:before {
  top: 0;
  border-top: 3px solid blue;
}
th:after {
  bottom: 0;
  border-bottom: 3px solid blue;
}
<div id="wrapper">
  <table>
    <thead>
      <tr>
        <th>A</th>
        <th>B</th>
        <th>C</th>
        <th>D</th>
        <th>E</th>
      </tr>
    </thead>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
      <td>2</td>
    </tr>
    <tr>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
    </tr>
    <tr>
      <td>4</td>
      <td>4</td>
      <td>4</td>
      <td>4</td>
      <td>4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>5</td>
      <td>5</td>
      <td>5</td>
      <td>5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>6</td>
      <td>6</td>
      <td>6</td>
      <td>6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>7</td>
      <td>7</td>
      <td>7</td>
      <td>7</td>
    </tr>
    <tr>
      <td>8</td>
      <td>8</td>
      <td>8</td>
      <td>8</td>
      <td>8</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tr>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
      <td>9</td>
    </tr>
    <tbody>
    </tbody>
  </table>
</div>

Position Sticky and Table Headers, But you can sticky a , which means you can make sticky headers inside a regular ol' . It makes way more sense to sticky a parent element like the table header stickiness requires position: relative to work and that doesn't apply to <thead> to replicate the style of a table, but not locked out of using position: relative and  The reason for that is that when an element is given the position: sticky style, the sticky item’s container is the only area in which the sticky item can stick. The item doesn’t have any

Now I can set the border styles with psuedo classes as user @soulshined suggested. Belows are css changes to work and here is JSFiddle Link. Already tested on chrome and firefox.

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

        table {
          width: 100%;
          text-align: center;
          border-collapse: collapse;
        }
        table tr th {
          border: 1px solid green;
        }
        table tr th:first-child {
          border-left: 1px solid green;
        }
        table tr td {
          border: 1px solid green;
        }

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

        th::before {
            content: '';
            position: absolute;
            left: 0;
            width: 100%;
            height: 100%;
            border-right: 1px solid green;
            display: block;
            top : 1px;
        }

        th::after {
            content: '';
            position: absolute;
            left: 0;
            width: 100%;
            height: 100%;
            border-bottom: 1px solid green;
            border-top: 1px solid green;
            display: block;
            top : -1px;
        }

Border style do not work with sticky position element, I don't know why my border style do not work with position: sticky; attribute. I would like to set border styles on my sticky table header. But I don't want to use the  You can't position: sticky; a . Nor a . But you can sticky a , which means you can make sticky headers inside a regular ol' . This is tricky stuff,

Tried some of the existing answers, but as comments have mentioned, they result in a one pixel gap between the borders.

Made a workaround, though it requires JavaScript. It places a <div> in each <th>, on resize it fits the <div> to the <th>. The <th> border is then instead applied to the <div>.

Note that as of writing this, position: sticky is not working in Chromium on <thead>, it works in Firefox. However, the position: sticky related CSS does not affect the page, if the JavaScript is not executed.

Click Run code snippet to see if it works, in your browser.

function onResize() {
    $("thead th div").each(function () {
        var width = $(this).parent().outerWidth() - 2; // -2 * border-width
        $(this).css("width", width + "px");
    });
}

$("thead th").each(function () {
    $(this).append($("<div>"));
});

$(window).on("resize", onResize);
onResize();
table {
    width: 100%;
    border-collapse: collapse;
}

th {
    text-align: left;
}

th, td {
    padding: 12px 20px;

    border: 1px solid rgba(0, 0, 0, 0.125);
}

table thead {
    position: sticky;
    top: 0;

    background: #FFF;
}

/* Used as a workaround for position: sticky not rendering the border */
thead th div {
    width: 30px;
    margin: 0 -20px; /* -20px to negate the 20px from the padding */
    position: absolute;
    top: 0;
    bottom: 0;
    z-index: -1;

    border-right: 1px solid rgba(0, 0, 0, 0.125);
    border-bottom: 1px solid rgba(0, 0, 0, 0.125);
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

<table>
    <thead>
        <tr>
            <th>A</th>
            <th>B</th>
            <th>C</th>
            <th>D</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>

        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>

        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>

        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
    </tbody>
</table>

Making Elements Stick in CSS Using position: sticky ← Alligator.io, It allows us to make elements stick when the scroll reaches a certain point. Note we don't have to use flexbox at all for position: sticky to work, here it's just that Plus, these are affiliate links, so if you purchase a course you help Alligator​.io <div class="item pirate"> <img src="/images/pirate.svg" width="100" alt="​Item 1">  The element is positioned relative to its normal position, so "left:20px" adds 20 pixels to the element's LEFT position. The element is positioned based on the user's scroll position. A sticky element toggles between relative and fixed, depending on the scroll position. It is positioned relative until a given offset position is met in the

CSS Position Sticky - How It Really Works! - Elad Shechter, The problem is that sometimes it works while other times it doesn't. The reason for that is that when an element is given the position: sticky style, the sticky  A sticky element toggles between relative and fixed, depending on the scroll position. It is positioned relative until a given offset position is met in the viewport - then it "sticks" in place (like position:fixed). Note: Internet Explorer, Edge 15 and earlier versions do not support sticky positioning. Safari requires a -webkit- prefix (see

position: sticky is Amazing, It's like a position:fixed element that's a sleeper agent spy. Sticky position is perfect for things like the iOS style list headings. border: 1px solid #ccc; If your app is running in an older browser that doesn't support position:sticky , then that  Since sticky is first treated as relative (or should be), z-index would have no effect. For browsers which do support sticky, I’m not sure they would support the change in z-index from relative to fixed position. Browser support for position sticky: No support for Internet Explorer or Edge.

How To Create a Sticky Element, Note: This example does not work in Internet Explorer or Edge 15 and earlier An element with position: sticky; is positioned based on the user's scroll position. CSS sticky position is a brilliant tool if you simply need a plain sticky element. If your need grows beyond that though—say you want to add some fancy effects upon the sticky element—you’ll still be better off opting for a JavaScript solution, be that self-written, or a library like Waypoints.js with its sticky module .

Comments
  • you didn't provide a color for your table tr th, table tr td selector. Syntax should be as follows border: <unit> <border-style> <color>
  • @soulshined No , actually it doesn't need. <color> part is not mendatory. Default is #000000 AFAIK.
  • interesting. learned something new!
  • This approach solves the problem at the root and is easy to understand. I think this should be preferred over using pseudo-classes.
  • Yeah but when i use this there seems to a one pixel gap along the unused border sides
  • brother, saved my day :)))
  • This solution is neat but unfortunately, there seem to be a bug in Edge that prevents it from working.
  • Thank you for updated answer. But still doesn't work for left and right, isn't ?
  • See edit @Cataclysm and let me know your thoughts. I just put the table border back, or do you want them to be of a certain color separate of table border color?
  • Thank you ! Now I'm almost done with your idea .Here is updated fiddle
  • @soulshined Thanks a lot mate ! you saved me!! :)
  • I already tried like that. You should scroll down this and check what happened to thead style.