7

It seems like sticky doesn't work on <td> with colspan. Is there a way around it?

body {
  font-family: 'Lucida Grande';
}

div {
  width: 500px;
  height: 200px;
  overflow: scroll;
}

td,
th {
  padding: 2px 5px;
  white-space: nowrap;
}

.sticky-header {
  position: sticky;
  position: -webkit-sticky;
  top: 0;
  background: #146775;
  color: white;
  z-index: 3;
}

.sticky-header:first-child {
  left: 0;
  z-index: 4;
}

.sticky-row {
  position: sticky;
  position: -webkit-sticky;
  left: 0;
  top: 23px; /* This seems to work differently for Safari, FF, Chrome etc. Here adjusted for FF */
  background: #1C4464;
  color: white;
  z-index: 3;
}
.sticky-row:nth-child(2) {
  left: 100px; /* How can I make this dynamic? */
  z-index: 2;
}
span {
  position: absolute;
  top: 2px;
  left: 113px;
}

.sticky-column {
  position: sticky;
  position: -webkit-sticky;
  left: 0;
  background: #569CA8;
  color: white;
  z-index: 1;
  width: 100px; /* How can I make this dynamic? */
}
<div>
  <table cellspacing="0">
    <thead>
      <tr>
        <td class="sticky-header">Header 1</td>
        <td class="sticky-header">Header 2</td>
        <td class="sticky-header">Header 3</td>
        <td class="sticky-header">Header 4</td>
        <td class="sticky-header">Header 5</td>
        <td class="sticky-header">Header 7</td>
        <td class="sticky-header">Header 8</td>
        <td class="sticky-header">Header 9</td>
        <td class="sticky-header">Header 10</td>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="sticky-row">Sticky Row 1</td>
        <td class="sticky-row" colspan="9">How can I make this sticky?</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-row">Sticky Row 2<span>Dirty way of making sticky</span></td>
        <td class="sticky-row" colspan="9"></td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-row">Sticky Row 3</td>
        <td class="sticky-row" colspan="9">How can I make this sticky?</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
      <tr>
        <td class="sticky-column">Column 1</td>
        <td>Column 2</td>
        <td>Column 3</td>
        <td>Column 4</td>
        <td>Column 5</td>
        <td>Column 7</td>
        <td>Column 8</td>
        <td>Column 9</td>
        <td>Column 10</td>
      </tr>
    </tbody>
  </table>
</div>
SeaBass
  • 1,584
  • 4
  • 20
  • 46
  • 1
    I think it goes against the purpose of tabular display, can't this part be outside of the `table`? – Kaddath Jan 16 '19 at 08:26
  • 1
    @Kaddath My table is much more complex and contains both sticky columns to the left, a sticky header and sticky rows when scrolling down. The row with the colspan functions as a row-divider so there are multiple of those. I've had things outside of the table before and it's a mess to sync up with scrolls and changes of column widths unfortunately. – SeaBass Jan 16 '19 at 08:30
  • Hum i see, can your example snippet be a little more representative of what you have then? – Kaddath Jan 16 '19 at 08:34
  • For reference : https://stackoverflow.com/questions/12266262/position-sticky-on-thead – Alexandre Elshobokshy Jan 16 '19 at 08:38
  • @Kaddath Updated the snippet! – SeaBass Jan 16 '19 at 08:50
  • I figured out a dirty way of achieving what I want. Check out the second blue row in the snippet! :) Suggestions of a better solution are welcome. – SeaBass Jan 16 '19 at 09:16
  • @SeaBass the thing is now when you scroll down, the row 2 "Dirty way" superimposes with the row 3 "How can I".. – Kaddath Jan 16 '19 at 11:09
  • Yes, I had to add a background to that text. Getting filthier and filthier hehe. – SeaBass Jan 16 '19 at 18:21

3 Answers3

4

Actually it's already sticky, the problem is due to the width of the td there is no reason for it to move. So to make them both sticky change the colspan on the second td (to make it even better give it also a left of 50px to make them move next to each other). Hope this awnsered your question.

UPDATE:

the colspan on the 2nd td is why your code doesn't work, i fixed this by replacing the structure to this

<tr class="darkblue">
    <td class="sticky-row">Sticky Row 1</td>
    <td class="sticky-row" colspan>How can I make this sticky?</td>
    <td colspan="8"></td>
  </tr>

and added an extra css class to fix the background color of the tr

.darkblue {
  background: #1C4464;
  width: 100%;
}

.sticky-row {
  position: sticky;
  position: -webkit-sticky;
  left: 0;
  top: 23px;
  color: white;
  z-index: 3;
}

Full code for reference down below

    body {
  font-family: 'Lucida Grande';
}

div {
  width: 500px;
  height: 200px;
  overflow: scroll;
}

td,
th {
  padding: 2px 5px;
  white-space: nowrap;
}

.sticky-header {
  position: sticky;
  position: -webkit-sticky;
  top: 0;
  background: #146775;
  color: white;
  z-index: 3;
}

.sticky-header:first-child {
  left: 0;
  z-index: 4;
}

.darkblue {
  background: #1C4464;
  width: 100%;
}

.sticky-row {
  position: sticky;
  position: -webkit-sticky;
  left: 0;
  top: 23px;
  /* background: #1C4464; */
  color: white;
  z-index: 3;
}
.sticky-row:nth-child(2) {
  left: 100px; /* How can I make this dynamic? */
  z-index: 2;
}
span {
  position: absolute;
  top: 2px;
  left: 113px;
}

.sticky-column {
  position: sticky;
  position: -webkit-sticky;
  left: 0;
  background: #569CA8;
  color: white;
  z-index: 1;
  width: 100px; /* How can I make this dynamic? */
}
<div>
  <table cellspacing="0">
<thead>
  <tr>
    <td class="sticky-header">Header 1</td>
    <td class="sticky-header">Header 2</td>
    <td class="sticky-header">Header 3</td>
    <td class="sticky-header">Header 4</td>
    <td class="sticky-header">Header 5</td>
    <td class="sticky-header">Header 7</td>
    <td class="sticky-header">Header 8</td>
    <td class="sticky-header">Header 9</td>
    <td class="sticky-header">Header 10</td>
  </tr>
</thead>
<tbody>
  <tr class="darkblue">
    <td class="sticky-row">Sticky Row 1</td>
    <td class="sticky-row" colspan>How can I make this sticky?</td>
    <td colspan="8"></td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr  class="darkblue">
    <td class="sticky-row">Sticky Row 2<span>Dirty way of making sticky</span></td>
    <td class="sticky-row" colspan="9"></td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-row">Sticky Row 3</td>
    <td class="sticky-row" colspan="9">How can I make this sticky?</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
  <tr>
    <td class="sticky-column">Column 1</td>
    <td>Column 2</td>
    <td>Column 3</td>
    <td>Column 4</td>
    <td>Column 5</td>
    <td>Column 7</td>
    <td>Column 8</td>
    <td>Column 9</td>
    <td>Column 10</td>
  </tr>
</tbody>
  </table>
</div>
Seregmir
  • 548
  • 1
  • 5
  • 16
  • Will try, but colspan 1? Isn't that a little ugly? Also is there a way to make it dynamic so I don't have to set 50px exactly? – SeaBass Jan 16 '19 at 08:52
  • It might but you can change it to whatever you want, i just used 1 to illustrate my solution. – Seregmir Jan 16 '19 at 08:53
  • hm, it actually wont work for me with an inexact colspan. Look how your text got divided into 5 lines. I need that on one line and setting white-space: nowrap makes the column above/below change in width too :/ – SeaBass Jan 16 '19 at 09:04
  • I updated my original post with one way that gives me what I want. – SeaBass Jan 16 '19 at 09:17
  • Thank you! The blue row background disappears and only the text stays. Also the Column 2 gets the same width as the sticky row second column. – SeaBass Jan 16 '19 at 18:27
  • You have to add the *darkblue* class to the blue rows to show the background again. This probably will fix the width aswell – Seregmir Jan 17 '19 at 07:31
  • Do you think I can use the `` and `` tags for this or are they basically functioning like `` and ``? – SeaBass Jan 18 '19 at 19:08
  • 1
    @Seregmir thank you dear friend! just saved my day ❤️ – Danila Ganchar Feb 17 '21 at 13:02
0

Here is the Solution for your original Question. Trying to help would be useless if you have a varying Question and keep changing the Question

position: sticky doesn't work with table elements. Since, top and bottom doesn't work in table elements what we can do is line height of the non sticky td so that sticky td wouldn't overlap over non-sticky td

<div>
    <table>
        <tr>
            <td class="sticky left">Sticky</td>
            <td class="sticky" colspan="9">How can I make this sticky?</td>
        </tr>
        <tr class="tableBody">
            <td>Column 1</td>
            <td>Column 2</td>
            <td>Column 3</td>
            <td>Column 4</td>
            <td>Column 5</td>
            <td>Column 7</td>
            <td>Column 8</td>
            <td>Column 9</td>
            <td>Column 10</td>
        </tr>
    </table>
</div>

Add class left for the sticky td that remains on the left side. Similarly manage the value of left in other td . Also, add some class for non sticky td as tableBody in this example:

div {
  width: 300px;
  overflow: scroll;
}
.sticky {
  position: fixed;
  left: 50px;
  background: white;
}
.left{
  left:0;
}
tr.tableBody
{
   line-height:50px;
}

Finally add your desired CSS.

Please check this DEMO Fiddle Here

Sushil
  • 1,111
  • 1
  • 10
  • 23
  • @IslamElshobokshy didn't notice that OP has changed his Question – Sushil Jan 16 '19 at 09:07
  • My original question is the same. I fleshed it out because it was requested. Thanks for the help. And sticky does work on table elements. – SeaBass Jan 16 '19 at 18:25
0

Here's another not-too-ugly hack:

<tr>
   <th>
      <div class="outer_container">
         <div class="inner_container">
            Sticky Heading
         </div>
      </div>
      &nbsp;
   </th>
</tr>

th {
    position: sticky;
    left: 0;
}

.outer_container {
    position: relative;
}

.inner_container {
    position: absolute;
    width: 200px;
}

The non-breaking space &nbsp; gives the <th> its normal behavior in terms of padding, margin, line-height etc.

Also, you need to set the width of your inner_container which is also kinda ugly and not so dynamic but it works.

PussInBoots
  • 11,028
  • 9
  • 52
  • 84