Search code examples
jqueryhtmlcsssticky

sticky first row of table with the same column width


I'm trying to create sticky first row of table (header), but when i do it, the header has different column width.

When the table is loaded it looks like:

   |   heada    |   headb    |   headc    |   headd    |
   |  contenta  |  contentb  |  contentc  |  contentd  |
   |  contenta  |  contentb  |  contentc  |  contentd  |

When i scroll down it looks like:

   | heada | headb | headc | headd |                   |
   |  contenta  |  contentb  |  contentc  |  contentd  |
   |  contenta  |  contentb  |  contentc  |  contentd  |

html/php:

if(mysql_num_rows($show_firm) >0)
{
  echo '<table class="tableList">';

       // first tr/header

  echo'<tr class="tableListforstickymenu">';        

       foreach($show_columns_firm as $key => $v)
       {
          echo '<td class="tableList-TD-first">'.$v.'</td>';
       }
  echo '</tr>';

      // other tr

  while($r = mysql_fetch_assoc($show_firm))
  {                 
      echo'<tr class="tableList">';
      foreach($show_columns_firm as $key => $v)
      {
          echo '<td class="tableList-TD-first">'.$v.'</td>';
      }
      echo '</tr></table>';
  }
 }

css:

.tableListforstickymenu {
    border: 1px solid #DBF4FF;
    background-color: #B9DBE8;
    border-collapse: collapse; 
    text-align: left;
    overflow-wrap: break-word;
    table-layout: fixed;
    padding: 10px 1px;
    margin: 0px auto;
}
.stickymenu {
    position: fixed;
    width: 100%;
    left: 0;
    top: 130px;
    z-index: 100;
    border: 0;
}

jQuery:

$(document).ready(function()
 {
   var stickyNavTop = $('.tableListforstickymenu').offset().top;

   var stickyNav = function()
    {
        var scrollTop = $(window).scrollTop();

        if (scrollTop > stickyNavTop) 
        { 
            $('.tableListforstickymenu').addClass('stickymenu');
        }
        else 
        {
            $('.tableListforstickymenu').removeClass('stickymenu'); 
        }
  };
  stickyNav();
  $(window).scroll(function()
  {
      stickyNav();
  });
 }); 

I don't know how to align the first sticky row (header) with rest of table. One more thing: table is wider than screen (its about 30 columns and has scrolls).


Solution

  • I believe it's a CSS / HTML issue, I've split your table into two (awkward things happen when you start splitting html tables in this way) - it's better practice to use css only for layout situations like this and not html tables (this split will need to be reflected in your php) then your css should address the width of both tables. Your js should now be adapted to target the top table.

    change the class label of your initial table declaration at the top of your php and in the middle of your php change:

    echo '</tr>';
    

    to:

    echo '</tr></table><table class="tableList"><tr class="tableList">';
    

    should do the trick

    snippet here:

    $(document).ready(function()
     {
       var stickyNavTop = $('.tableListforstickymenu').offset().top;
    
       var stickyNav = function()
        {
            var scrollTop = $(window).scrollTop(),
            		scrollLeft= $(window).scrollLeft();
    
            if (scrollTop > stickyNavTop) 
            { 
                $('.tableList-top').addClass('stickymenu');
            }
            else 
            {
                $('.tableList-top').removeClass('stickymenu'); 
            }
            
            $('.stickymenu').css({ left: -scrollLeft + 8 }); // the +8 is due to the padding you have on the main table css
            
      };
      stickyNav();
      $(window).scroll(function()
      {
          stickyNav();
      });
     });
    .tableListforstickymenu {
        border: 1px solid #DBF4FF;
        background-color: #B9DBE8;
        border-collapse: collapse; 
        text-align: left;
        table-layout: fixed;
        overflow-wrap: break-word;
        padding: 10px 1px;
        margin: 0px auto;
    }
    .stickymenu{
        position: fixed;
        top: 0px;
        left: 10px;
        table-layout: fixed;
        z-index: 100;
        border: 0;
    }
    
    table.tableList-top td, table.tableList td{
      min-width: 5em; /* recommend using em's or px and not % here */
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <table class="tableList-top">
        <tr class="tableListforstickymenu">
            <td class="tableList-TD-first">alpha</td>
            <td class="tableList-TD-first">bravo</td>
            <td class="tableList-TD-first">charlie</td>
            <td class="tableList-TD-first">delta</td>
            <td class="tableList-TD-first">echo</td>
        </tr>
    </table>
    
    <table class="tableList">
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    <tr class="tableList">
    <td class="tableList-TD-first">content_a</td>
    <td class="tableList-TD-first">content_b</td>
    <td class="tableList-TD-first">content_c</td>
    <td class="tableList-TD-first">content_d</td>
    <td class="tableList-TD-first">content_e</td>
    </tr>
    
    </table>