wake-up-neo.com

HTML-Tabelle mit festen Kopfzeilen?

Gibt es eine browserübergreifende CSS/JavaScript-Technik, um eine lange HTML-Tabelle anzuzeigen, so dass die Spaltenüberschriften auf dem Bildschirm fixiert bleiben und nicht mit dem Tabellenkörper scrollen. Denken Sie an den "Einfrierbereich" -Effekt in Microsoft Excel.

Ich möchte in der Lage sein, durch den Inhalt der Tabelle zu blättern, aber immer die Spaltenüberschriften oben sehen zu können.

219
Cheekysoft

Ich habe eine Zeit lang nach einer Lösung dafür gesucht und festgestellt, dass die meisten Antworten nicht funktionieren oder für meine Situation nicht geeignet sind. Deshalb habe ich mit jQuery eine einfache Lösung geschrieben.

Dies ist die Lösungsübersicht:

  1. Klonen Sie die Tabelle, die einen festen Header haben muss, und platzieren Sie die geklonte Kopie .__ auf dem Original.
  2. Entfernen Sie den Tischkörper vom oberen Tisch.
  3. Entfernen Sie den Tabellenkopf aus der unteren Tabelle.
  4. Passen Sie die Spaltenbreite an. (Wir verfolgen die ursprünglichen Spaltenbreiten)

Unten ist der Code in einer ausführbaren Demo.

function scrolify(tblAsJQueryObject, height) {
  var oTbl = tblAsJQueryObject;

  // for very large tables you can remove the four lines below
  // and wrap the table with <div> in the mark-up and assign
  // height and overflow property  
  var oTblDiv = $("<div/>");
  oTblDiv.css('height', height);
  oTblDiv.css('overflow', 'scroll');
  oTbl.wrap(oTblDiv);

  // save original width
  oTbl.attr("data-item-original-width", oTbl.width());
  oTbl.find('thead tr td').each(function() {
    $(this).attr("data-item-original-width", $(this).width());
  });
  oTbl.find('tbody tr:eq(0) td').each(function() {
    $(this).attr("data-item-original-width", $(this).width());
  });


  // clone the original table
  var newTbl = oTbl.clone();

  // remove table header from original table
  oTbl.find('thead tr').remove();
  // remove table body from new table
  newTbl.find('tbody tr').remove();

  oTbl.parent().parent().prepend(newTbl);
  newTbl.wrap("<div/>");

  // replace ORIGINAL COLUMN width				
  newTbl.width(newTbl.attr('data-item-original-width'));
  newTbl.find('thead tr td').each(function() {
    $(this).width($(this).attr("data-item-original-width"));
  });
  oTbl.width(oTbl.attr('data-item-original-width'));
  oTbl.find('tbody tr:eq(0) td').each(function() {
    $(this).width($(this).attr("data-item-original-width"));
  });
}

$(document).ready(function() {
  scrolify($('#tblNeedsScrolling'), 160); // 160 is height
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>

<div style="width:300px;border:6px green solid;">
  <table border="1" width="100%" id="tblNeedsScrolling">
    <thead>
      <tr><th>Header 1</th><th>Header 2</th></tr>
    </thead>
    <tbody>
      <tr><td>row 1, cell 1</td><td>row 1, cell 2</td></tr>
      <tr><td>row 2, cell 1</td><td>row 2, cell 2</td></tr>
      <tr><td>row 3, cell 1</td><td>row 3, cell 2</td></tr>
      <tr><td>row 4, cell 1</td><td>row 4, cell 2</td></tr>			
      <tr><td>row 5, cell 1</td><td>row 5, cell 2</td></tr>
      <tr><td>row 6, cell 1</td><td>row 6, cell 2</td></tr>
      <tr><td>row 7, cell 1</td><td>row 7, cell 2</td></tr>
      <tr><td>row 8, cell 1</td><td>row 8, cell 2</td></tr>			
    </tbody>
  </table>
</div>

Diese Lösung funktioniert in Chrome und IE. Da es auf jQuery basiert, sollte dies auch in anderen von jQuery unterstützten Browsern funktionieren.

84
Mahes

Dies kann in vier Codezeilen sauber gelöst werden.

Wenn Sie sich nur für moderne Browser interessieren, können Sie mit CSS-Transformationen einen festen Header einfacher erreichen. Hört sich seltsam an, funktioniert aber gut:

  • HTML und CSS bleiben unverändert.
  • Keine externen JavaScript-Abhängigkeiten.
  • Vier Zeilen Code.
  • Funktioniert für alle Konfigurationen (Tabellenlayout: fest usw.).
document.getElementById("wrap").addEventListener("scroll", function(){
   var translate = "translate(0,"+this.scrollTop+"px)";
   this.querySelector("thead").style.transform = translate;
});

Unterstützung für CSS-Transformationen ist weithin verfügbar mit Ausnahme von Internet Explorer 8-.

Hier ist das vollständige Beispiel als Referenz:

document.getElementById("wrap").addEventListener("scroll",function(){
   var translate = "translate(0,"+this.scrollTop+"px)";
   this.querySelector("thead").style.transform = translate;
});
/* Your existing container */
#wrap {
    overflow: auto;
    height: 400px;
}

/* CSS for demo */
td {
    background-color: green;
    width: 200px;
    height: 100px;
}
<div id="wrap">
    <table>
        <thead>
            <tr>
                <th>Foo</th>
                <th>Bar</th>
            </tr>
        </thead>
        <tbody>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
            <tr><td></td><td></td></tr>
        </tbody>
    </table>
</div>

168
Maximilian Hils

Ich habe gerade ein jQuery-Plugin zusammengestellt, das eine gültige Einzeltabelle mit gültigem HTML-Code (muss einen Thead und einen Tbody haben) annehmen und eine Tabelle mit festen Kopfzeilen und optionalen festen Fußzeilen ausgeben von Ihnen gewählter Inhalt (Seitenumbruch usw.). Wenn Sie größere Monitore nutzen möchten, ändert sich auch die Größe der Tabelle, wenn die Größe des Browsers geändert wird. Eine weitere Funktion ist das seitliche Scrollen, wenn die Tabellenspalten nicht alle in die Ansicht passen.

http://fixedheadertable.com/

auf github: http://markmalek.github.com/Fixed-Header-Table/

Es ist extrem einfach einzurichten und Sie können Ihre eigenen benutzerdefinierten Stile erstellen. Es verwendet auch abgerundete Ecken in allen Browsern. Denken Sie daran, dass ich es gerade veröffentlicht habe, also ist es immer noch technisch Beta und es gibt sehr wenige kleinere Probleme, die ich ausklammern kann.

Es funktioniert in Internet Explorer 7, Internet Explorer 8, Safari, Firefox und Chrome.

57
Mark

Ich habe auch ein Plugin erstellt, das dieses Problem behebt. Mein Projekt - jQuery.floatThead gibt es seit über 4 Jahren und ist sehr ausgereift.

Es erfordert keine externen Stile und erwartet nicht, dass Ihr Tisch in einer bestimmten Weise gestaltet wird. Es unterstützt Internet Explorer 9 + und Firefox/Chrome.

Derzeit (2018-05) hat es:

405 Commits und 998 Sterne auf GitHub


Viele (nicht alle) Antworten sind schnelle Hacks, die das Problem gelöst haben könnten, das eine Person hatte, aber nicht für jeden Tisch funktionieren.

Einige der anderen Plugins sind alt und funktionieren wahrscheinlich mit Internet Explorer gut, werden aber bei Firefox und Chrome nicht funktionieren.

23
mkoryak

TL; DR

Wenn Sie auf moderne Browser abzielen und keine extravaganten Styling-Anforderungen haben: http://jsfiddle.net/dPixie/byB9d/3/ ... Obwohl die big four-Version auch dies ziemlich süß ist Version verarbeitet Flüssigkeitsbreite viel besser.

Gute Nachrichten, Leute!

Mit den Fortschritten von HTML5 und CSS3 ist dies jetzt zumindest für moderne Browser möglich. Die etwas hackige Implementierung, die ich mir ausgedacht habe, kann hier gefunden werden: http://jsfiddle.net/dPixie/byB9d/3/ . Ich habe es in FX 25, Chrome 31 und IE 10 getestet ...

Relevantes HTML (fügen Sie jedoch einen HTML5-Doctype oben in Ihr Dokument ein):

<section class="positioned">
  <div class="container">
    <table>
      <thead>
        <tr class="header">
          <th>
            Table attribute name
            <div>Table attribute name</div>
          </th>
          <th>
            Value
            <div>Value</div>
          </th>
          <th>
            Description
            <div>Description</div>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>align</td>
          <td>left, center, right</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the alignment of a table according to surrounding text</td>
        </tr>
        <tr>
          <td>bgcolor</td>
          <td>rgb(x,x,x), #xxxxxx, colorname</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the background color for a table</td>
        </tr>
        <tr>
          <td>border</td>
          <td>1,""</td>
          <td>Specifies whether the table cells should have borders or not</td>
        </tr>
        <tr>
          <td>cellpadding</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between the cell wall and the cell content</td>
        </tr>
        <tr>
          <td>cellspacing</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between cells</td>
        </tr>
        <tr>
          <td>frame</td>
          <td>void, above, below, hsides, lhs, rhs, vsides, box, border</td>
          <td>Not supported in HTML5. Specifies which parts of the outside borders that should be visible</td>
        </tr>
        <tr>
          <td>rules</td>
          <td>none, groups, rows, cols, all</td>
          <td>Not supported in HTML5. Specifies which parts of the inside borders that should be visible</td>
        </tr>
        <tr>
          <td>summary</td>
          <td>text</td>
          <td>Not supported in HTML5. Specifies a summary of the content of a table</td>
        </tr>
        <tr>
          <td>width</td>
          <td>pixels, %</td>
          <td>Not supported in HTML5. Specifies the width of a table</td>
        </tr>
      </tbody>
    </table>
  </div>
</section>

Mit dieser CSS:

html, body{
  margin:0;
  padding:0;
  height:100%;
}
section {
  position: relative;
  border: 1px solid #000;
  padding-top: 37px;
  background: #500;
}
section.positioned {
  position: absolute;
  top:100px;
  left:100px;
  width:800px;
  box-shadow: 0 0 15px #333;
}
.container {
  overflow-y: auto;
  height: 200px;
}
table {
  border-spacing: 0;
  width:100%;
}
td + td {
  border-left:1px solid #eee;
}
td, th {
  border-bottom:1px solid #eee;
  background: #ddd;
  color: #000;
  padding: 10px 25px;
}
th {
  height: 0;
  line-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  color: transparent;
  border: none;
  white-space: nowrap;
}
th div{
  position: absolute;
  background: transparent;
  color: #fff;
  padding: 9px 25px;
  top: 0;
  margin-left: -25px;
  line-height: normal;
  border-left: 1px solid #800;
}
th:first-child div{
  border: none;
}

Aber wie?!

Einfach gesagt, Sie haben einen Tabellenheader, den Sie visuell ausblenden, indem Sie ihn auf 0px hoch setzen. Dieser enthält auch divs, die als fester Header verwendet werden. Der Tabellencontainer der Tabelle lässt oben genug Platz, um den absolut positionierten Header zu ermöglichen, und die Tabelle mit Bildlaufleisten erscheint wie erwartet.

Der obige Code verwendet die positionierte Klasse, um die Tabelle absolut zu positionieren (ich verwende sie in einem Popup-Dialogfeld). Sie können sie jedoch auch im Fluss des Dokuments verwenden, indem Sie die positioned-Klasse aus dem Container entfernen.

Aber ...

Es ist nicht perfekt. Firefox weigert sich, die Kopfzeile zu 0px zu machen (zumindest habe ich keinen Weg gefunden), hält es aber stur bei mindestens 4px ... Es ist kein großes Problem, aber abhängig von Ihrem Styling wird es Ihre Grenzen durchdringen usw.

Die Tabelle verwendet auch einen Faux-Spalten-Ansatz, bei dem die Hintergrundfarbe des Containers selbst als Hintergrund für die Header-Divs verwendet wird, die transparent sind.

Zusammenfassung

Insgesamt kann es je nach Ihren Anforderungen zu Stilproblemen kommen, insbesondere zu Grenzen oder komplizierten Hintergründen. Es könnte auch Probleme mit der Berechenbarkeit geben, ich habe es noch nicht in einer Vielzahl von Browsern eingecheckt (bitte kommentieren Sie Ihre Erfahrungen, wenn Sie es ausprobieren), aber ich habe nichts dergleichen gefunden sowieso ...

Alle Versuche, dieses Problem außerhalb der CSS-Spezifikation zu lösen, sind blasse Schatten dessen, was wir wirklich wollen: Lieferung auf das implizierte Versprechen von THEAD.

Dieses Problem mit eingefrorenen Kopfzeilen für eine Tabelle war lange Zeit eine offene Wunde in HTML/CSS.

In einer perfekten Welt würde es eine reine CSS-Lösung für dieses Problem geben. Leider scheint es keine gute zu geben.

Relevante Standards-Diskussionen zu diesem Thema sind:

UPDATE: Firefox hat in Version 32 position:sticky ausgeliefert. Jeder gewinnt!

19
djsadinoff

Hier ist ein jQuery-Plugin für feste Tabellenköpfe. Dadurch kann die gesamte Seite gescrollt werden, wodurch die Kopfzeile eingefroren wird, wenn sie den oberen Rand erreicht. Es funktioniert gut mit Twitter Bootstrap Tables.

GitHub-Repository: https://github.com/oma/table-fixed-header

Es wird nicht nur durch den Tabelleninhalt gescrollt. Sehen Sie sich andere Werkzeuge als eine dieser anderen Antworten an. Sie entscheiden, was am besten zu Ihnen passt.

14
oma

Die meisten hier veröffentlichten Lösungen erfordern jQuery. Wenn Sie eine rahmenunabhängige Lösung suchen, versuchen Sie Grid: http://www.matts411.com/post/grid/

Es wird auf Github hier gehostet: https://github.com/mmurph211/Grid

Es unterstützt nicht nur feste Kopfzeilen, sondern auch feste linke Spalten und Fußzeilen.

9
Matt

Eine verfeinerte reine CSS-Scrolltabelle

Allen reinen CSS-Lösungen, die ich bisher gesehen habe - so klug sie auch sein mögen - fehlt ein gewisses Maß an Klarheit oder sie funktionieren in manchen Situationen nicht richtig. Also entschied ich mich, mein eigenes zu schaffen ...

Eigenschaften:

  • Es ist reines CSS, daher ist keine jQuery erforderlich (oder überhaupt JavaScript-Code für diese Matter)
  • Sie können die Tabellenbreite auf einen Prozentsatz (a.k.a. "fluid") oder einen festen Wert einstellen oder den Inhalt seine Breite bestimmen lassen (a.k.a. "auto").
  • Säulenbreiten können auch fließend, fest oder automatisch sein.
  • Spalten werden aufgrund von horizontalem Bildlauf nie mit Kopfzeilen falsch ausgerichtet (ein Problem, das bei jeder anderen CSS-basierten Lösung auftritt, die ich gesehen habe und die keine festen Breiten erfordert).
  • Kompatibel mit allen gängigen Desktop-Browsern, einschließlich Internet Explorer bis Version 8
  • Sauberes, poliertes Aussehen; keine schlampig aussehenden 1-Pixel-Lücken oder fehlausgerichteten Ränder; sieht in allen Browsern gleich aus

Hier sind ein paar Geigen, die die Optionen für Fluid und automatische Breite zeigen:

  • Breite und Höhe der Flüssigkeit (passt sich der Bildschirmgröße an): - jsFiddle (Beachten Sie, dass die Bildlaufleiste nur angezeigt wird, wenn sie in dieser Konfiguration benötigt wird. Daher müssen Sie möglicherweise den Rahmen verkleinern, um ihn sehen zu können.)

  • Auto Width, Feste Höhe (einfacher in andere Inhalte zu integrieren): jsFiddle

Die Konfiguration für die automatische Breite, feste Höhe hat wahrscheinlich mehr Anwendungsfälle, daher werde ich den Code hier posten.

/* The following 'html' and 'body' rule sets are required only
   if using a % width or height*/

/*html {
  width: 100%;
  height: 100%;
}*/

body {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0 20px 0 20px;
  text-align: center;
}
.scrollingtable {
  box-sizing: border-box;
  display: inline-block;
  vertical-align: middle;
  overflow: hidden;
  width: auto; /* If you want a fixed width, set it here, else set to auto */
  min-width: 0/*100%*/; /* If you want a % width, set it here, else set to 0 */
  height: 188px/*100%*/; /* Set table height here; can be fixed value or % */
  min-height: 0/*104px*/; /* If using % height, make this large enough to fit scrollbar arrows + caption + thead */
  font-family: Verdana, Tahoma, sans-serif;
  font-size: 16px;
  line-height: 20px;
  padding: 20px 0 20px 0; /* Need enough padding to make room for caption */
  text-align: left;
}
.scrollingtable * {box-sizing: border-box;}
.scrollingtable > div {
  position: relative;
  border-top: 1px solid black;
  height: 100%;
  padding-top: 20px; /* This determines column header height */
}
.scrollingtable > div:before {
  top: 0;
  background: cornflowerblue; /* Header row background color */
}
.scrollingtable > div:before,
.scrollingtable > div > div:after {
  content: "";
  position: absolute;
  z-index: -1;
  width: 100%;
  height: 100%;
  left: 0;
}
.scrollingtable > div > div {
  min-height: 0/*43px*/; /* If using % height, make this large
                            enough to fit scrollbar arrows */
  max-height: 100%;
  overflow: scroll/*auto*/; /* Set to auto if using fixed
                               or % width; else scroll */
  overflow-x: hidden;
  border: 1px solid black; /* Border around table body */
}
.scrollingtable > div > div:after {background: white;} /* Match page background color */
.scrollingtable > div > div > table {
  width: 100%;
  border-spacing: 0;
  margin-top: -20px; /* Inverse of column header height */
  /*margin-right: 17px;*/ /* Uncomment if using % width */
}
.scrollingtable > div > div > table > caption {
  position: absolute;
  top: -20px; /*inverse of caption height*/
  margin-top: -1px; /*inverse of border-width*/
  width: 100%;
  font-weight: bold;
  text-align: center;
}
.scrollingtable > div > div > table > * > tr > * {padding: 0;}
.scrollingtable > div > div > table > thead {
  vertical-align: bottom;
  white-space: nowrap;
  text-align: center;
}
.scrollingtable > div > div > table > thead > tr > * > div {
  display: inline-block;
  padding: 0 6px 0 6px; /*header cell padding*/
}
.scrollingtable > div > div > table > thead > tr > :first-child:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 20px; /*match column header height*/
  border-left: 1px solid black; /*leftmost header border*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div > div:first-child,
.scrollingtable > div > div > table > thead > tr > * + :before {
  position: absolute;
  top: 0;
  white-space: pre-wrap;
  color: white; /*header row font color*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);}
.scrollingtable > div > div > table > thead > tr > * + :before {
  content: "";
  display: block;
  min-height: 20px; /* Match column header height */
  padding-top: 1px;
  border-left: 1px solid black; /* Borders between header cells */
}
.scrollingtable .scrollbarhead {float: right;}
.scrollingtable .scrollbarhead:before {
  position: absolute;
  width: 100px;
  top: -1px; /* Inverse border-width */
  background: white; /* Match page background color */
}
.scrollingtable > div > div > table > tbody > tr:after {
  content: "";
  display: table-cell;
  position: relative;
  padding: 0;
  border-top: 1px solid black;
  top: -1px; /* Inverse of border width */
}
.scrollingtable > div > div > table > tbody {vertical-align: top;}
.scrollingtable > div > div > table > tbody > tr {background: white;}
.scrollingtable > div > div > table > tbody > tr > * {
  border-bottom: 1px solid black;
  padding: 0 6px 0 6px;
  height: 20px; /* Match column header height */
}
.scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;}
.scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /* Alternate row color */
.scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /* Borders between body cells */
<div class="scrollingtable">
  <div>
    <div>
      <table>
        <caption>Top Caption</caption>
        <thead>
          <tr>
            <th><div label="Column 1"/></th>
            <th><div label="Column 2"/></th>
            <th><div label="Column 3"/></th>
            <th>
              <!-- More versatile way of doing column label; requires two identical copies of label -->
              <div><div>Column 4</div><div>Column 4</div></div>
            </th>
            <th class="scrollbarhead"/> <!-- ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW -->
          </tr>
        </thead>
        <tbody>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
        </tbody>
      </table>
    </div>
    Faux bottom caption
  </div>
</div>

<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->

Die Methode, die ich zum Einfrieren der Kopfzeile verwendet habe, ähnelt der von d-Pixie. Eine Erklärung dazu finden Sie in seinem Beitrag. Es gab eine Reihe von Fehlern und Einschränkungen bei dieser Technik, die nur durch eine Menge zusätzlicher CSS und ein oder zwei zusätzliche Div-Container behoben werden konnten.

6
DoctorDestructo

Ein einfaches jQuery-Plugin

Dies ist eine Variante der Lösung von Mahes. Sie können es wie $('table#foo').scrollableTable(); aufrufen

Die Idee ist:

  • Teilen Sie die Variablen thead und tbody in separate table-Elemente auf
  • Stellen Sie die Zellenbreiten wieder in Übereinstimmung
  • Wickeln Sie die zweite table in einen div.scrollable.
  • Verwenden Sie CSS, um div.scrollable tatsächlich zu scrollen

Das CSS könnte sein:

div.scrollable { height: 300px; overflow-y: scroll;}

Vorsichtsmaßnahmen

  • Wenn Sie diese Tabellen aufteilen, ist das Markup natürlich weniger semantisch. Ich bin nicht sicher, welche Auswirkungen dies auf die Zugänglichkeit hat.
  • Dieses Plugin behandelt keine Fußzeilen, mehrere Kopfzeilen usw.
  • Ich habe es nur in Chrome Version 20 getestet.

Das heißt, es funktioniert für meine Zwecke und Sie können es nehmen und ändern.

Hier ist das Plugin:

jQuery.fn.scrollableTable = function () {
  var $newTable, $oldTable, $scrollableDiv, originalWidths;
  $oldTable = $(this);

  // Once the tables are split, their cell widths may change. 
  // Grab these so we can make the two tables match again.
  originalWidths = $oldTable.find('tr:first td').map(function() {
    return $(this).width();
  });

  $newTable = $oldTable.clone();
  $oldTable.find('tbody').remove();
  $newTable.find('thead').remove();

  $.each([$oldTable, $newTable], function(index, $table) {
    $table.find('tr:first td').each(function(i) {
      $(this).width(originalWidths[i]);
    });
  });

  $scrollableDiv = $('<div/>').addClass('scrollable');
  $newTable.insertAfter($oldTable).wrap($scrollableDiv);
};
5
Nathan Long

Die CSS-Eigenschaft position: sticky wird in den meisten modernen Browsern hervorragend unterstützt (ich hatte Probleme mit Edge, siehe unten).

Dadurch können wir das Problem der festen Header ganz leicht lösen:

thead th { position: sticky; top: 0; }

Safari benötigt ein Herstellerpräfix: -webkit-sticky.

Für Firefox musste ich min-height: 0 zu einem der übergeordneten Elemente hinzufügen. Ich vergesse genau, warum dies nötig war.

Leider scheint die Microsoft Edge-Implementierung nur teilweise zu funktionieren. Zumindest hatte ich flackernde und falsch ausgerichtete Tabellenzellen in meinen Tests. Der Tisch war noch nutzbar, hatte jedoch erhebliche ästhetische Probleme.

4
Daniel Waltrip

:) 

Nicht so sauber, aber reine HTML/CSS-Lösung.

table {
    overflow-x:scroll;
}

tbody {
    max-height: /*your desired max height*/
    overflow-y:scroll;
    display:block;
}

Aktualisiert für IE8 + JSFiddle-Beispiel

4
Anton Matyulkov

Unterstützung für feste Fußzeile

Ich habe Nathans Funktion erweitert, um auch eine feste Fußzeile und maximale Höhe zu unterstützen. Die Funktion wird auch das CSS selbst festlegen, und Sie müssen nur eine Breite unterstützen.

Verwendungszweck:

Feste Höhe:

$('table').scrollableTable({ height: 100 });

Maximale Höhe (wenn der Browser die CSS-Option "max-height" unterstützt):

$('table').scrollableTable({ maxHeight: 100 });

Skript:

jQuery.fn.scrollableTable = function(options) {

    var $originalTable, $headTable, $bodyTable, $footTable, $scrollableDiv, originalWidths;

    // Prepare the separate parts of the table
    $originalTable = $(this);
    $headTable = $originalTable.clone();

    $headTable.find('tbody').remove();
    $headTable.find('tfoot').remove();

    $bodyTable = $originalTable.clone();
    $bodyTable.find('thead').remove();
    $bodyTable.find('tfoot').remove();

    $footTable = $originalTable.clone();
    $footTable.find('thead').remove();
    $footTable.find('tbody').remove();

    // Grab the original column widths and set them in the separate tables
    originalWidths = $originalTable.find('tr:first td').map(function() {
        return $(this).width();
    });

    $.each([$headTable, $bodyTable, $footTable], function(index, $table) {
        $table.find('tr:first td').each(function(i) {
            $(this).width(originalWidths[i]);
        });
    });

    // The div that makes the body table scroll
    $scrollableDiv = $('<div/>').css({
        'overflow-y': 'scroll'
    });

    if(options.height) {
        $scrollableDiv.css({'height': options.height});
    }
    else if(options.maxHeight) {
        $scrollableDiv.css({'max-height': options.maxHeight});
    }

    // Add the new separate tables and remove the original one
    $headTable.insertAfter($originalTable);
    $bodyTable.insertAfter($headTable);
    $footTable.insertAfter($bodyTable);
    $bodyTable.wrap($scrollableDiv);
    $originalTable.remove();
};
3
gitaarik

Zwei Divs, eines für Header und eines für Daten. Machen Sie die Daten div scrollbar und verwenden Sie JavaScript, um die Breite der Spalten im Header so festzulegen, dass sie der Breite der Daten entspricht. Ich denke, dass die Breite der Datenspalten nicht dynamisch, sondern fest sein muss.

2
cjk

Mir ist klar, dass die Frage JavaScript zulässt, aber hier ist eine reine CSS-Lösung, die ich aufgearbeitet habe und die die Tabelle horizontal erweitern kann. Es wurde mit Internet Explorer 10 und den neuesten Chrome- und Firefox-Browsern getestet. Ein Link zu jsFiddle befindet sich unten.

Das HTML:

Putting some text here to differentiate between the header
aligning with the top of the screen and the header aligning
with the top of one of its ancestor containers.

<div id="positioning-container">
<div id="scroll-container">
    <table>
        <colgroup>
            <col class="col1"></col>
            <col class="col2"></col>
        </colgroup>
        <thead>
            <th class="header-col1"><div>Header 1</div></th>
            <th class="header-col2"><div>Header 2</div></th>
        </thead>
        <tbody>
            <tr><td>Cell 1.1</td><td>Cell 1.2</td></tr>
            <tr><td>Cell 2.1</td><td>Cell 2.2</td></tr>
            <tr><td>Cell 3.1</td><td>Cell 3.2</td></tr>
            <tr><td>Cell 4.1</td><td>Cell 4.2</td></tr>
            <tr><td>Cell 5.1</td><td>Cell 5.2</td></tr>
            <tr><td>Cell 6.1</td><td>Cell 6.2</td></tr>
            <tr><td>Cell 7.1</td><td>Cell 7.2</td></tr>

        </tbody>
    </table>
</div>
</div>

Und das CSS:

table{
    border-collapse: collapse;
    table-layout: fixed;
    width: 100%;
}
/* Not required, just helps with alignment for this example */
td, th{
    padding: 0;
    margin: 0;
}

tbody{
    background-color: #ddf;
}

thead {
    /* Keeps the header in place. Don't forget top: 0 */
    position: absolute;
    top: 0;
    background-color: #ddd;

    /* The 17px is to adjust for the scrollbar width.
     * This is a new css value that makes this pure
     * css example possible */
    width: calc(100% - 17px);
    height: 20px;
}

/* Positioning container. Required to position the
 * header since the header uses position:absolute
 * (otherwise it would position at the top of the screen) */
#positioning-container{
    position: relative;
}

/* A container to set the scroll-bar and
 * includes padding to move the table contents
 * down below the header (padding = header height) */
#scroll-container{
    overflow-y: auto;
    padding-top: 20px;
    height: 100px;
}
.header-col1{
    background-color: red;
}

/* Fixed-width header columns need a div to set their width */
.header-col1 div{
    width: 100px;
}

/* Expandable columns need a width set on the th tag */
.header-col2{
    width: 100%;
}
.col1 {
    width: 100px;
}
.col2{
    width: 100%;
}

http://jsfiddle.net/HNHRv/3/

1
bzuillsmith

Für diejenigen, die die Nice-Lösung von Maximilian Hils ausprobierten und es nicht geschafft haben, sie mit dem Internet Explorer zu verwenden, hatte ich das gleiche Problem (Internet Explorer 11) und fand heraus, was das Problem war.

In Internet Explorer 11 funktioniert die Stilumwandlung (zumindest bei translate) nicht für <THEAD>. Ich habe dieses Problem gelöst, indem ich stattdessen den Stil auf alle <TH>s in einer Schleife angewendet habe. Das hat funktioniert. Mein JavaScript-Code sieht folgendermaßen aus:

document.getElementById('pnlGridWrap').addEventListener("scroll", function () {
  var translate = "translate(0," + this.scrollTop + "px)";
  var myElements = this.querySelectorAll("th");
  for (var i = 0; i < myElements.length; i++) {
    myElements[i].style.transform=translate;
  }
});

In meinem Fall war die Tabelle eine GridView in ASP.NET. Zuerst dachte ich, es war, weil es keinen <THEAD> hatte, aber selbst wenn ich es zwang, einen zu haben, funktionierte es nicht. Dann habe ich herausgefunden, was ich oben geschrieben habe.

Es ist eine sehr schöne und einfache Lösung. Bei Chrome ist es perfekt, bei Firefox etwas ruckelig und bei Internet Explorer noch ruckeliger. Aber alles in allem eine gute Lösung.

1
Magnus

Hier ist eine Lösung, mit der wir am Ende gearbeitet haben (um einige Edge-Fälle und ältere Versionen von Internet Explorer zu behandeln, haben wir schließlich auch die Titelleiste beim Scrollen ausgeblendet und dann wieder eingeblendet, wenn das Scrollen beendet ist, aber in Firefox- und WebKit-Browsern Diese Lösung funktioniert einfach. Es wird davon ausgegangen, dass der Zusammenbruch von Border: Collapse.

Der Schlüssel zu dieser Lösung besteht darin, dass nach dem Anwenden von border-collapse die CSS-Transformationen auf den Header angewendet werden. Es ist also nur eine Frage des Abblätterns von Scroll-Ereignissen und der korrekten Einstellung der Transformation. Sie müssen nichts kopieren. Da dieses Verhalten nicht ordnungsgemäß im Browser implementiert wird, ist eine schwerere Lösung kaum vorstellbar.

JSFiddle: http://jsfiddle.net/podperson/tH9VU/2/

Es ist als einfaches jQuery-Plugin implementiert. Sie machen einfach Ihren Thead mit einem Anruf wie $ ('thead'). Sticky () klebrig, und sie hängen herum. Es funktioniert für mehrere Tische auf einer Seite und Kopfabschnitte, die sich an großen Tischen befinden.

$.fn.sticky = function(){
    $(this).each( function(){
        var thead = $(this),
            tbody = thead.next('tbody');

        updateHeaderPosition();

        function updateHeaderPosition(){
            if(
                thead.offset().top < $(document).scrollTop()
                && tbody.offset().top + tbody.height() > $(document).scrollTop()
            ){
                var tr = tbody.find('tr').last(),
                    y = tr.offset().top - thead.height() < $(document).scrollTop()
                        ? tr.offset().top - thead.height() - thead.offset().top
                        : $(document).scrollTop() - thead.offset().top;

                thead.find('th').css({
                    'z-index': 100,
                    'transform': 'translateY(' + y + 'px)',
                    '-webkit-transform': 'translateY(' + y + 'px)'
                });
            } else {
                thead.find('th').css({
                    'transform': 'none',
                    '-webkit-transform': 'none'
                });
            }
        }

        // See http://www.quirksmode.org/dom/events/scroll.html
        $(window).on('scroll', updateHeaderPosition);
    });
}

$('thead').sticky();
0
podperson

Ich habe ein einfaches, leichtes jQuery-Plug-In entwickelt, um eine gut formatierte HTML-Tabelle in eine scrollbare Tabelle mit festem Tabellenkopf und Spalten zu konvertieren.

Das Plugin funktioniert gut, um die Pixel-zu-Pixel-Positionierung des festen Abschnitts mit dem scrollbaren Abschnitt abzugleichen. Darüber hinaus können Sie auch die Anzahl der Spalten einfrieren, die beim horizontalen Scrollen immer sichtbar sind. 

Demo & Dokumentation: http://meetselva.github.io/fixed-table-rows-cols/ 

GitHub-Repository: https://github.com/meetselva/fixed-table-rows-cols

Nachfolgend finden Sie die Verwendung für eine einfache Tabelle mit festem Header.

$(<table selector>).fxdHdrCol({
    width:     "100%",
    height:    200,
    colModal: [{width: 30, align: 'center'},
               {width: 70, align: 'center'}, 
               {width: 200, align: 'left'}, 
               {width: 100, align: 'center'}, 
               {width: 70, align: 'center'}, 
               {width: 250, align: 'center'}
              ]
});
0

Hier ist eine verbesserte Antwort auf die von Maximilian Hils .

Dieses funktioniert in Internet Explorer 11 ohne jegliches Flimmern:

var headerCells = tableWrap.querySelectorAll("thead td");
for (var i = 0; i < headerCells.length; i++) {
    var headerCell = headerCells[i];
    headerCell.style.backgroundColor = "silver";
}
var lastSTop = tableWrap.scrollTop;
tableWrap.addEventListener("scroll", function () {
    var stop = this.scrollTop;
    if (stop < lastSTop) {
        // Resetting the transform for the scrolling up to hide the headers
        for (var i = 0; i < headerCells.length; i++) {
            headerCells[i].style.transitionDelay = "0s";
            headerCells[i].style.transform = "";
        }
    }
    lastSTop = stop;
    var translate = "translate(0," + stop + "px)";
    for (var i = 0; i < headerCells.length; i++) {
        headerCells[i].style.transitionDelay = "0.25s";
        headerCells[i].style.transform = translate;
    }
});
0
user4617883

Ich habe diese Problemumgehung gefunden - Kopfzeile in einer Tabelle über der Tabelle mit Daten verschieben:

<html>
<head>
	<title>Fixed header</title>
	<style>
		table td {width:75px;}
	</style>
</head>

<body>
<div style="height:auto; width:350px; overflow:auto">
<table border="1">
<tr>
	<td>header 1</td>
	<td>header 2</td>
	<td>header 3</td>
</tr>
</table>
</div>

<div style="height:50px; width:350px; overflow:auto">
<table border="1">
<tr>
	<td>row 1 col 1</td>
	<td>row 1 col 2</td>
	<td>row 1 col 3</td>		
</tr>
<tr>
	<td>row 2 col 1</td>
	<td>row 2 col 2</td>
	<td>row 2 col 3</td>		
</tr>
<tr>
	<td>row 3 col 1</td>
	<td>row 3 col 2</td>
	<td>row 3 col 3</td>		
</tr>
<tr>
	<td>row 4 col 1</td>
	<td>row 4 col 2</td>
	<td>row 4 col 3</td>		
</tr>
<tr>
	<td>row 5 col 1</td>
	<td>row 5 col 2</td>
	<td>row 5 col 3</td>		
</tr>
<tr>
	<td>row 6 col 1</td>
	<td>row 6 col 2</td>
	<td>row 6 col 3</td>		
</tr>
</table>
</div>


</body>
</html>

0
Leonid Alzhin

Wenn Sie das Plugin StickyTableHeaders jQuery auf die Tabelle anwenden, bleiben die Spaltenköpfe am oberen Rand des Ansichtsfensters, wenn Sie nach unten scrollen. 

Beispiel:

$(function () {
    $("table").stickyTableHeaders();
});

/*! Copyright (c) 2011 by Jonas Mosbech - https://github.com/jmosbech/StickyTableHeaders
	MIT license info: https://github.com/jmosbech/StickyTableHeaders/blob/master/license.txt */

;
(function ($, window, undefined) {
    'use strict';

    var name = 'stickyTableHeaders',
        id = 0,
        defaults = {
            fixedOffset: 0,
            leftOffset: 0,
            marginTop: 0,
            scrollableArea: window
        };

    function Plugin(el, options) {
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;

        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el;
        base.id = id++;
        base.$window = $(window);
        base.$document = $(document);

        // Listen for destroyed, call teardown
        base.$el.bind('destroyed',
        $.proxy(base.teardown, base));

        // Cache DOM refs for performance reasons
        base.$clonedHeader = null;
        base.$originalHeader = null;

        // Keep track of state
        base.isSticky = false;
        base.hasBeenSticky = false;
        base.leftOffset = null;
        base.topOffset = null;

        base.init = function () {
            base.$el.each(function () {
                var $this = $(this);

                // remove padding on <table> to fix issue #7
                $this.css('padding', 0);

                base.$originalHeader = $('thead:first', this);
                base.$clonedHeader = base.$originalHeader.clone();
                $this.trigger('clonedHeader.' + name, [base.$clonedHeader]);

                base.$clonedHeader.addClass('tableFloatingHeader');
                base.$clonedHeader.css('display', 'none');

                base.$originalHeader.addClass('tableFloatingHeaderOriginal');

                base.$originalHeader.after(base.$clonedHeader);

                base.$printStyle = $('<style type="text/css" media="print">' +
                    '.tableFloatingHeader{display:none !important;}' +
                    '.tableFloatingHeaderOriginal{position:static !important;}' +
                    '</style>');
                $('head').append(base.$printStyle);
            });

            base.setOptions(options);
            base.updateWidth();
            base.toggleHeaders();
            base.bind();
        };

        base.destroy = function () {
            base.$el.unbind('destroyed', base.teardown);
            base.teardown();
        };

        base.teardown = function () {
            if (base.isSticky) {
                base.$originalHeader.css('position', 'static');
            }
            $.removeData(base.el, 'plugin_' + name);
            base.unbind();

            base.$clonedHeader.remove();
            base.$originalHeader.removeClass('tableFloatingHeaderOriginal');
            base.$originalHeader.css('visibility', 'visible');
            base.$printStyle.remove();

            base.el = null;
            base.$el = null;
        };

        base.bind = function () {
            base.$scrollableArea.on('scroll.' + name, base.toggleHeaders);
            if (!base.isWindowScrolling) {
                base.$window.on('scroll.' + name + base.id, base.setPositionValues);
                base.$window.on('resize.' + name + base.id, base.toggleHeaders);
            }
            base.$scrollableArea.on('resize.' + name, base.toggleHeaders);
            base.$scrollableArea.on('resize.' + name, base.updateWidth);
        };

        base.unbind = function () {
            // unbind window events by specifying handle so we don't remove too much
            base.$scrollableArea.off('.' + name, base.toggleHeaders);
            if (!base.isWindowScrolling) {
                base.$window.off('.' + name + base.id, base.setPositionValues);
                base.$window.off('.' + name + base.id, base.toggleHeaders);
            }
            base.$scrollableArea.off('.' + name, base.updateWidth);
        };

        base.toggleHeaders = function () {
            if (base.$el) {
                base.$el.each(function () {
                    var $this = $(this),
                        newLeft,
                        newTopOffset = base.isWindowScrolling ? (
                        isNaN(base.options.fixedOffset) ? base.options.fixedOffset.outerHeight() : base.options.fixedOffset) : base.$scrollableArea.offset().top + (!isNaN(base.options.fixedOffset) ? base.options.fixedOffset : 0),
                        offset = $this.offset(),

                        scrollTop = base.$scrollableArea.scrollTop() + newTopOffset,
                        scrollLeft = base.$scrollableArea.scrollLeft(),

                        scrolledPastTop = base.isWindowScrolling ? scrollTop > offset.top : newTopOffset > offset.top,
                        notScrolledPastBottom = (base.isWindowScrolling ? scrollTop : 0) < (offset.top + $this.height() - base.$clonedHeader.height() - (base.isWindowScrolling ? 0 : newTopOffset));

                    if (scrolledPastTop && notScrolledPastBottom) {
                        newLeft = offset.left - scrollLeft + base.options.leftOffset;
                        base.$originalHeader.css({
                            'position': 'fixed',
                                'margin-top': base.options.marginTop,
                                'left': newLeft,
                                'z-index': 3 // #18: opacity bug
                        });
                        base.leftOffset = newLeft;
                        base.topOffset = newTopOffset;
                        base.$clonedHeader.css('display', '');
                        if (!base.isSticky) {
                            base.isSticky = true;
                            // make sure the width is correct: the user might have resized the browser while in static mode
                            base.updateWidth();
                        }
                        base.setPositionValues();
                    } else if (base.isSticky) {
                        base.$originalHeader.css('position', 'static');
                        base.$clonedHeader.css('display', 'none');
                        base.isSticky = false;
                        base.resetWidth($('td,th', base.$clonedHeader), $('td,th', base.$originalHeader));
                    }
                });
            }
        };

        base.setPositionValues = function () {
            var winScrollTop = base.$window.scrollTop(),
                winScrollLeft = base.$window.scrollLeft();
            if (!base.isSticky || winScrollTop < 0 || winScrollTop + base.$window.height() > base.$document.height() || winScrollLeft < 0 || winScrollLeft + base.$window.width() > base.$document.width()) {
                return;
            }
            base.$originalHeader.css({
                'top': base.topOffset - (base.isWindowScrolling ? 0 : winScrollTop),
                    'left': base.leftOffset - (base.isWindowScrolling ? 0 : winScrollLeft)
            });
        };

        base.updateWidth = function () {
            if (!base.isSticky) {
                return;
            }
            // Copy cell widths from clone
            if (!base.$originalHeaderCells) {
                base.$originalHeaderCells = $('th,td', base.$originalHeader);
            }
            if (!base.$clonedHeaderCells) {
                base.$clonedHeaderCells = $('th,td', base.$clonedHeader);
            }
            var cellWidths = base.getWidth(base.$clonedHeaderCells);
            base.setWidth(cellWidths, base.$clonedHeaderCells, base.$originalHeaderCells);

            // Copy row width from whole table
            base.$originalHeader.css('width', base.$clonedHeader.width());
        };

        base.getWidth = function ($clonedHeaders) {
            var widths = [];
            $clonedHeaders.each(function (index) {
                var width, $this = $(this);

                if ($this.css('box-sizing') === 'border-box') {
                    width = $this[0].getBoundingClientRect().width; // #39: border-box bug
                } else {
                    var $origTh = $('th', base.$originalHeader);
                    if ($origTh.css('border-collapse') === 'collapse') {
                        if (window.getComputedStyle) {
                            width = parseFloat(window.getComputedStyle(this, null).width);
                        } else {
                            // ie8 only
                            var leftPadding = parseFloat($this.css('padding-left'));
                            var rightPadding = parseFloat($this.css('padding-right'));
                            // Needs more investigation - this is assuming constant border around this cell and it's neighbours.
                            var border = parseFloat($this.css('border-width'));
                            width = $this.outerWidth() - leftPadding - rightPadding - border;
                        }
                    } else {
                        width = $this.width();
                    }
                }

                widths[index] = width;
            });
            return widths;
        };

        base.setWidth = function (widths, $clonedHeaders, $origHeaders) {
            $clonedHeaders.each(function (index) {
                var width = widths[index];
                $origHeaders.eq(index).css({
                    'min-width': width,
                        'max-width': width
                });
            });
        };

        base.resetWidth = function ($clonedHeaders, $origHeaders) {
            $clonedHeaders.each(function (index) {
                var $this = $(this);
                $origHeaders.eq(index).css({
                    'min-width': $this.css('min-width'),
                        'max-width': $this.css('max-width')
                });
            });
        };

        base.setOptions = function (options) {
            base.options = $.extend({}, defaults, options);
            base.$scrollableArea = $(base.options.scrollableArea);
            base.isWindowScrolling = base.$scrollableArea[0] === window;
        };

        base.updateOptions = function (options) {
            base.setOptions(options);
            // scrollableArea might have changed
            base.unbind();
            base.bind();
            base.updateWidth();
            base.toggleHeaders();
        };

        // Run initializer
        base.init();
    }

    // A plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[name] = function (options) {
        return this.each(function () {
            var instance = $.data(this, 'plugin_' + name);
            if (instance) {
                if (typeof options === 'string') {
                    instance[options].apply(instance);
                } else {
                    instance.updateOptions(options);
                }
            } else if (options !== 'destroy') {
                $.data(this, 'plugin_' + name, new Plugin(this, options));
            }
        });
    };

})(jQuery, window);
body {
    margin: 0 auto;
    padding: 0 20px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 11px;
    color: #555;
}
table {
    border: 0;
    padding: 0;
    margin: 0 0 20px 0;
    border-collapse: collapse;
}
th {
    padding: 5px;
    /* NOTE: th padding must be set explicitly in order to support IE */
    text-align: right;
    font-weight:bold;
    line-height: 2em;
    color: #FFF;
    background-color: #555;
}
tbody td {
    padding: 10px;
    line-height: 18px;
    border-top: 1px solid #E0E0E0;
}
tbody tr:nth-child(2n) {
    background-color: #F7F7F7;
}
tbody tr:hover {
    background-color: #EEEEEE;
}
td {
    text-align: right;
}
td:first-child, th:first-child {
    text-align: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div style="width:3000px">some really really wide content goes here</div>
<table>
    <thead>
        <tr>
            <th colspan="9">Companies listed on NASDAQ OMX Copenhagen.</th>
        </tr>
        <tr>
            <th>Full name</th>
            <th>CCY</th>
            <th>Last</th>
            <th>+/-</th>
            <th>%</th>
            <th>Bid</th>
            <th>Ask</th>
            <th>Volume</th>
            <th>Turnover</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>A.P. Møller...</td>
            <td>DKK</td>
            <td>33,220.00</td>
            <td>760</td>
            <td>2.34</td>
            <td>33,140.00</td>
            <td>33,220.00</td>
            <td>594</td>
            <td>19,791,910</td>
        </tr>
        <tr>
            <td>A.P. Møller...</td>
            <td>DKK</td>
            <td>34,620.00</td>
            <td>640</td>
            <td>1.88</td>
            <td>34,620.00</td>
            <td>34,700.00</td>
            <td>9,954</td>
            <td>346,530,246</td>
        </tr>
        <tr>
            <td>Carlsberg A</td>
            <td>DKK</td>
            <td>380</td>
            <td>0</td>
            <td>0</td>
            <td>371</td>
            <td>391.5</td>
            <td>6</td>
            <td>2,280</td>
        </tr>
        <tr>
            <td>Carlsberg B</td>
            <td>DKK</td>
            <td>364.4</td>
            <td>8.6</td>
            <td>2.42</td>
            <td>363</td>
            <td>364.4</td>
            <td>636,267</td>
            <td>228,530,601</td>
        </tr>
        <tr>
            <td>Chr. Hansen...</td>
            <td>DKK</td>
            <td>114.5</td>
            <td>-1.6</td>
            <td>-1.38</td>
            <td>114.2</td>
            <td>114.5</td>
            <td>141,822</td>
            <td>16,311,454</td>
        </tr>
        <tr>
            <td>Coloplast B</td>
            <td>DKK</td>
            <td>809.5</td>
            <td>11</td>
            <td>1.38</td>
            <td>809</td>
            <td>809.5</td>
            <td>85,840</td>
            <td>69,363,301</td>
        </tr>
        <tr>
            <td>D/S Norden</td>
            <td>DKK</td>
            <td>155</td>
            <td>-1.5</td>
            <td>-0.96</td>
            <td>155</td>
            <td>155.1</td>
            <td>51,681</td>
            <td>8,037,225</td>
        </tr>
        <tr>
            <td>Danske Bank</td>
            <td>DKK</td>
            <td>69.05</td>
            <td>2.55</td>
            <td>3.83</td>
            <td>69.05</td>
            <td>69.2</td>
            <td>1,723,719</td>
            <td>115,348,068</td>
        </tr>
        <tr>
            <td>DSV</td>
            <td>DKK</td>
            <td>105.4</td>
            <td>0.2</td>
            <td>0.19</td>
            <td>105.2</td>
            <td>105.4</td>
            <td>674,873</td>
            <td>71,575,035</td>
        </tr>
        <tr>
            <td>FLSmidth &amp; Co.</td>
            <td>DKK</td>
            <td>295.8</td>
            <td>-1.8</td>
            <td>-0.6</td>
            <td>295.1</td>
            <td>295.8</td>
            <td>341,263</td>
            <td>100,301,032</td>
        </tr>
        <tr>
            <td>G4S plc</td>
            <td>DKK</td>
            <td>22.53</td>
            <td>0.05</td>
            <td>0.22</td>
            <td>22.53</td>
            <td>22.57</td>
            <td>190,920</td>
            <td>4,338,150</td>
        </tr>
        <tr>
            <td>Jyske Bank</td>
            <td>DKK</td>
            <td>144.2</td>
            <td>1.4</td>
            <td>0.98</td>
            <td>142.8</td>
            <td>144.2</td>
            <td>78,163</td>
            <td>11,104,874</td>
        </tr>
        <tr>
            <td>Københavns ...</td>
            <td>DKK</td>
            <td>1,580.00</td>
            <td>-12</td>
            <td>-0.75</td>
            <td>1,590.00</td>
            <td>1,620.00</td>
            <td>82</td>
            <td>131,110</td>
        </tr>
        <tr>
            <td>Lundbeck</td>
            <td>DKK</td>
            <td>103.4</td>
            <td>-2.5</td>
            <td>-2.36</td>
            <td>103.4</td>
            <td>103.8</td>
            <td>157,162</td>
            <td>16,462,282</td>
        </tr>
        <tr>
            <td>Nordea Bank</td>
            <td>DKK</td>
            <td>43.22</td>
            <td>-0.06</td>
            <td>-0.14</td>
            <td>43.22</td>
            <td>43.25</td>
            <td>167,520</td>
            <td>7,310,143</td>
        </tr>
        <tr>
            <td>Novo Nordisk B</td>
            <td>DKK</td>
            <td>552.5</td>
            <td>-3.5</td>
            <td>-0.63</td>
            <td>550.5</td>
            <td>552.5</td>
            <td>843,533</td>
            <td>463,962,375</td>
        </tr>
        <tr>
            <td>Novozymes B</td>
            <td>DKK</td>
            <td>805.5</td>
            <td>5.5</td>
            <td>0.69</td>
            <td>805</td>
            <td>805.5</td>
            <td>152,188</td>
            <td>121,746,199</td>
        </tr>
        <tr>
            <td>Pandora</td>
            <td>DKK</td>
            <td>39.04</td>
            <td>0.94</td>
            <td>2.47</td>
            <td>38.8</td>
            <td>39.04</td>
            <td>350,965</td>
            <td>13,611,838</td>
        </tr>
        <tr>
            <td>Rockwool In...</td>
            <td>DKK</td>
            <td>492</td>
            <td>0</td>
            <td>0</td>
            <td>482</td>
            <td>492</td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>Rockwool In...</td>
            <td>DKK</td>
            <td>468</td>
            <td>12</td>
            <td>2.63</td>
            <td>465.2</td>
            <td>468</td>
            <td>9,885</td>
            <td>4,623,850</td>
        </tr>
        <tr>
            <td>Sydbank</td>
            <td>DKK</td>
            <td>95</td>
            <td>0.05</td>
            <td>0.05</td>
            <td>94.7</td>
            <td>95</td>
            <td>103,438</td>
            <td>9,802,899</td>
        </tr>
        <tr>
            <td>TDC</td>
            <td>DKK</td>
            <td>43.6</td>
            <td>0.13</td>
            <td>0.3</td>
            <td>43.5</td>
            <td>43.6</td>
            <td>845,110</td>
            <td>36,785,339</td>
        </tr>
        <tr>
            <td>Topdanmark</td>
            <td>DKK</td>
            <td>854</td>
            <td>13.5</td>
            <td>1.61</td>
            <td>854</td>
            <td>855</td>
            <td>38,679</td>
            <td>32,737,678</td>
        </tr>
        <tr>
            <td>Tryg</td>
            <td>DKK</td>
            <td>290.4</td>
            <td>0.3</td>
            <td>0.1</td>
            <td>290</td>
            <td>290.4</td>
            <td>94,587</td>
            <td>27,537,247</td>
        </tr>
        <tr>
            <td>Vestas Wind...</td>
            <td>DKK</td>
            <td>90.15</td>
            <td>-4.2</td>
            <td>-4.45</td>
            <td>90.1</td>
            <td>90.15</td>
            <td>1,317,313</td>
            <td>121,064,314</td>
        </tr>
        <tr>
            <td>William Dem...</td>
            <td>DKK</td>
            <td>417.6</td>
            <td>0.1</td>
            <td>0.02</td>
            <td>417</td>
            <td>417.6</td>
            <td>64,242</td>
            <td>26,859,554</td>
        </tr>
    </tbody>
</table>
<div style="height: 4000px">lots of content down here...</div>

0
shilovk

Viele Leute scheinen nach dieser Antwort zu suchen. Ich fand es in einer Antwort auf eine andere Frage hier vergraben: Synchronisieren der Spaltenbreite von Tabellen in zwei verschiedenen Frames usw.

Von den Dutzenden von Methoden, die ich ausprobiert habe, ist dies die einzige Methode, die ich gefunden habe und die zuverlässig funktioniert, damit Sie eine untere Bildlauf-Tabelle haben können, deren Kopf-Tabelle die gleichen Breiten hat.

So habe ich es gemacht, zuerst habe ich jsfiddle oben verbessert, um diese Funktion zu erstellen, die sowohl auf td als auch auf th anwendbar ist (falls dies andere auslöst, die th für das Styling ihrer Kopfzeilen verwenden).

var setHeaderTableWidth= function (headertableid,basetableid) {
            $("#"+headertableid).width($("#"+basetableid).width());
            $("#"+headertableid+" tr th").each(function (i) {
                $(this).width($($("#"+basetableid+" tr:first td")[i]).width());
            });
            $("#" + headertableid + " tr td").each(function (i) {
                $(this).width($($("#" + basetableid + " tr:first td")[i]).width());
            });
        }

Als Nächstes müssen Sie zwei Tabellen erstellen. HINWEIS: Die Headertabelle sollte eine zusätzliche TD haben, um Platz in der oberen Tabelle für die Bildlaufleiste zu belassen:

 <table id="headertable1" class="input-cells table-striped">
        <thead>
            <tr style="background-color:darkgray;color:white;"><th>header1</th><th>header2</th><th>header3</th><th>header4</th><th>header5</th><th>header6</th><th></th></tr>
        </thead>
     </table>
    <div id="resizeToBottom" style="overflow-y:scroll;overflow-x:hidden;">
        <table id="basetable1" class="input-cells table-striped">
            <tbody >
                <tr>
                    <td>testdata</td>
                    <td>2</td>
                    <td>3</td>
                    <td>4</span></td>
                    <td>55555555555555</td>
                    <td>test</td></tr>
            </tbody>
        </table>
    </div>

Dann mache etwas wie:

        setHeaderTableWidth('headertable1', 'basetable1');
        $(window).resize(function () {
            setHeaderTableWidth('headertable1', 'basetable1');
        });

Dies ist die einzige Lösung, die ich bei Stack Overflow gefunden habe und die aus vielen ähnlichen gestellten Fragen funktioniert, die in allen meinen Fällen funktionieren.

Ich habe beispielsweise das jQuery stickytables-Plugin ausprobiert, das nicht mit Durandal funktioniert, und das Google-Code-Projekt hier https://code.google.com/p/js-scroll-table-header/issues/detail?id= 2

Andere Lösungen, die das Klonen der Tabellen betreffen, haben eine schlechte Leistung oder sind schlecht und funktionieren nicht in allen Fällen.

Diese zu komplexen Lösungen sind nicht erforderlich. Erstellen Sie einfach zwei Tabellen wie in den folgenden Beispielen, und rufen Sie die Funktion setHeaderTableWidth wie hier beschrieben auf. Boom, Sie sind fertig.

Wenn dies für Sie nicht funktioniert, haben Sie wahrscheinlich mit Ihrer CSS-Box-Size-Eigenschaft gespielt und müssen sie korrekt einstellen. Es ist leicht, Ihren CSS-Inhalt aus Versehen zu vermasseln. Es gibt viele Dinge, die schief gehen können. Seien Sie sich also dessen bewusst. Dieser Ansatz funktioniert für mich.

0
pilavdzice

Ich mag Maximillian Hils ' antworte, aber ich hatte ein paar Probleme:

  1. die Transformation funktioniert in Edge oder IE nur, wenn Sie sie auf th anwenden
  2. die Kopfzeile flackert beim Blättern in Edge und IE
  3. meine Tabelle wird mit ajax geladen. Daher wollte ich eher an das Fenster-Scroll-Ereignis als an das Scroll-Ereignis des Wrappers anhängen

Um das Flimmern zu beseitigen, verwende ich eine Zeitüberschreitung, um zu warten, bis der Benutzer das Scrollen beendet hat. Dann wende ich die Transformation an - so dass die Kopfzeile beim Scrollen nicht sichtbar ist. 

Ich habe dies auch mit jQuery geschrieben, ein Vorteil davon ist, dass jQuery Herstellerpräfixe für Sie handhaben soll

    var isScrolling, lastTop, lastLeft, isLeftHidden, isTopHidden;

    //Scroll events don't bubble https://stackoverflow.com/a/19375645/150342
    //so can't use $(document).on("scroll", ".table-container-fixed", function (e) {
    document.addEventListener('scroll', function (event) {
        var $container = $(event.target);
        if (!$container.hasClass("table-container-fixed"))
            return;    

        //transform needs to be applied to th for Edge and IE
        //in this example I am also fixing the leftmost column
        var $topLeftCell = $container.find('table:first > thead > tr > th:first');
        var $headerCells = $topLeftCell.siblings();
        var $columnCells = $container
           .find('table:first > tbody > tr > td:first-child, ' +
                 'table:first > tfoot > tr > td:first-child');

        //hide the cells while returning otherwise they show on top of the data
        if (!isLeftHidden) {
            var currentLeft = $container.scrollLeft();
            if (currentLeft < lastLeft) {
                //scrolling left
                isLeftHidden = true;
                $topLeftCell.css('visibility', 'hidden');
                $columnCells.css('visibility', 'hidden');
            }
            lastLeft = currentLeft;
        }

        if (!isTopHidden) {
            var currentTop = $container.scrollTop();
            if (currentTop < lastTop) {
                //scrolling up
                isTopHidden = true;
                $topLeftCell.css('visibility', 'hidden');
                $headerCells.css('visibility', 'hidden');
            }
            lastTop = currentTop;
        }

        // Using timeout to delay transform until user stops scrolling
        // Clear timeout while scrolling
        window.clearTimeout(isScrolling);

        // Set a timeout to run after scrolling ends
        isScrolling = setTimeout(function () {
            //move the table cells. 
            var x = $container.scrollLeft();
            var y = $container.scrollTop();

            $topLeftCell.css('transform', 'translate(' + x + 'px, ' + y + 'px)');
            $headerCells.css('transform', 'translateY(' + y + 'px)');
            $columnCells.css('transform', 'translateX(' + x + 'px)');

            isTopHidden = isLeftHidden = false;
            $topLeftCell.css('visibility', 'inherit');
            $headerCells.css('visibility', 'inherit');
            $columnCells.css('visibility', 'inherit');
        }, 100);

    }, true);

Die Tabelle wird in ein div mit der Klasse table-container-fixed eingeschlossen.

.table-container-fixed{
    overflow: auto;
    height: 400px;
}

Ich habe den Rand-Collapse-Parameter auf "Separieren" gesetzt, da ansonsten der Rand beim Übersetzen verloren geht und ich den Rand des Tisches entferne, um zu verhindern, dass der Inhalt direkt über der Zelle erscheint, in der sich der Rand beim Scrollen befand.

.table-container-fixed > table {
   border-collapse: separate;
   border:none;
}

Ich mache den Hintergrund th weiß, um die darunter liegenden Zellen zu bedecken, und füge einen Rand hinzu, der mit dem Tabellenrand übereinstimmt - der mithilfe von Bootstrap gestaltet und aus dem Bildlauf gescrollt wird.

 .table-container-fixed > table > thead > tr > th {
        border-top: 1px solid #ddd !important;
        background-color: white;        
        z-index: 10;
        position: relative;/*to make z-index work*/
    }

            .table-container-fixed > table > thead > tr > th:first-child {
                z-index: 20;
            }

.table-container-fixed > table > tbody > tr > td:first-child,
.table-container-fixed > table > tfoot > tr > td:first-child {
    background-color: white;        
    z-index: 10;
    position: relative;
}
0
Colin

Dies ist keine exakte Lösung für die feste Kopfzeile, aber ich habe eine ziemlich raffinierte Methode geschaffen, um die Kopfzeile in der langen Tabelle zu wiederholen, aber trotzdem die Sortierfähigkeit behalten.

Diese nette kleine Option erfordert das Plugin jQuery tablesorter . So funktioniert das:

HTML

<table class="tablesorter boxlist" id="pmtable">
    <thead class="fixedheader">
        <tr class="boxheadrow">
            <th width="70px" class="header">Job Number</th>
            <th width="10px" class="header">Pri</th>
            <th width="70px" class="header">CLLI</th>
            <th width="35px" class="header">Market</th>
            <th width="35px" class="header">Job Status</th>
            <th width="65px" class="header">Technology</th>
            <th width="95px;" class="header headerSortDown">MEI</th>
            <th width="95px" class="header">TEO Writer</th>
            <th width="75px" class="header">Quote Due</th>
            <th width="100px" class="header">Engineer</th>
            <th width="75px" class="header">ML Due</th>
            <th width="75px" class="header">ML Complete</th>
            <th width="75px" class="header">SPEC Due</th>
            <th width="75px" class="header">SPEC Complete</th>
            <th width="100px" class="header">Install Supervisor</th>
            <th width="75px" class="header">MasTec OJD</th>
            <th width="75px" class="header">Install Start</th>
            <th width="30px" class="header">Install Hours</th>
            <th width="75px" class="header">Revised CRCD</th>
            <th width="75px" class="header">Latest Ship-To-Site</th>
            <th width="30px" class="header">Total Parts</th>
            <th width="30px" class="header">OEM Rcvd</th>
            <th width="30px" class="header">Minor Rcvd</th>
            <th width="30px" class="header">Total Received</th>
            <th width="30px" class="header">% On Site</th>
            <th width="60px" class="header">Actions</th>
        </tr>
    </thead>
        <tbody class="scrollable">
            <tr data-job_id="3548" data-ml_id="" class="odd">
                <td class="c black">FL-8-RG9UP</td>
                <td data-pri="2" class="priority c yellow">M</td>
                <td class="c">FTLDFLOV</td>
                <td class="c">SFL</td>
                <td class="c">NOI</td>
                <td class="c">TRANSPORT</td>
                <td class="c"></td>
                <td class="c">Chris Byrd</td>
                <td class="c">Apr 13, 2013</td>
                <td class="c">Kris Hall</td>
                <td class="c">May 20, 2013</td>
                <td class="c">May 20, 2013</td>
                <td class="c">Jun 5, 2013</td>
                <td class="c">Jun 7, 2013</td>
                <td class="c">Joseph Fitz</td>
                <td class="c">Jun 10, 2013</td>
                <td class="c">TBD</td>
                <td class="c">123</td>
                <td class="c revised_crcd"><input readonly="true" name="revised_crcd" value="Jul 26, 2013" type="text" size="12" class="smInput r_crcd c hasDatepicker" id="dp1377194058616"></td>
                <td class="c">TBD</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="actions"><span style="float:left;" class="ui-icon ui-icon-folder-open editJob" title="View this job" s="" details'=""></span></td>
            </tr>
            <tr data-job_id="4264" data-ml_id="2959" class="even">
                <td class="c black">MTS13009SF</td>
                <td data-pri="2" class="priority c yellow">M</td>
                <td class="c">OJUSFLTL</td>
                <td class="c">SFL</td>
                <td class="c">NOI</td>
                <td class="c">TRANSPORT</td>
                <td class="c"></td>
                <td class="c">DeMarcus Stewart</td>
                <td class="c">May 22, 2013</td>
                <td class="c">Ryan Alsobrook</td>
                <td class="c">Jun 19, 2013</td>
                <td class="c">Jun 27, 2013</td>
                <td class="c">Jun 19, 2013</td>
                <td class="c">Jul 4, 2013</td>
                <td class="c">Randy Williams</td>
                <td class="c">Jun 21, 2013</td>
                <td class="c">TBD</td>
                <td class="c">95</td>
                <td class="c revised_crcd"><input readonly="true" name="revised_crcd" value="Aug 9, 2013" type="text" size="12" class="smInput r_crcd c hasDatepicker" id="dp1377194058632"></td><td class="c">TBD</td>
                <td class="c">0</td>
                <td class="c">0.00%</td>
                <td class="c">0.00%</td>
                <td class="c">0.00%</td>
                <td class="c">0.00%</td>
                <td class="actions"><span style="float:left;" class="ui-icon ui-icon-folder-open editJob" title="View this job" s="" details'=""></span><input style="float:left;" type="hidden" name="req_ship" class="reqShip hasDatepicker" id="dp1377194058464"><span style="float:left;" class="ui-icon ui-icon-calendar requestShip" title="Schedule this job for shipping"></span><span class="ui-icon ui-icon-info viewOrderInfo" style="float:left;" title="Show material details for this order"></span></td>
            </tr>
            .
            .
            .
            .
            <tr class="boxheadrow repeated-header">
                <th width="70px" class="header">Job Number</th>
                <th width="10px" class="header">Pri</th>
                <th width="70px" class="header">CLLI</th>
                <th width="35px" class="header">Market</th>
                <th width="35px" class="header">Job Status</th>
                <th width="65px" class="header">Technology</th>
                <th width="95px;" class="header">MEI</th>
                <th width="95px" class="header">TEO Writer</th>
                <th width="75px" class="header">Quote Due</th>
                <th width="100px" class="header">Engineer</th>
                <th width="75px" class="header">ML Due</th>
                <th width="75px" class="header">ML Complete</th>
                <th width="75px" class="header">SPEC Due</th>
                <th width="75px" class="header">SPEC Complete</th>
                <th width="100px" class="header">Install Supervisor</th>
                <th width="75px" class="header">MasTec OJD</th>
                <th width="75px" class="header">Install Start</th>
                <th width="30px" class="header">Install Hours</th>
                <th width="75px" class="header">Revised CRCD</th>
                <th width="75px" class="header">Latest Ship-To-Site</th>
                <th width="30px" class="header">Total Parts</th>
                <th width="30px" class="header">OEM Rcvd</th>
                <th width="30px" class="header">Minor Rcvd</th>
                <th width="30px" class="header">Total Received</th>
                <th width="30px" class="header">% On Site</th>
                <th width="60px" class="header">Actions</th>
            </tr>

Meine Tabelle hat offensichtlich viel mehr Zeilen als diese. Um genau zu sein, können Sie jedoch sehen, wo sich die Kopfzeile wiederholt. Die sich wiederholende Kopfzeile wird von dieser Funktion eingerichtet:

jQuery

// Clone the original header row and add the "repeated-header" class
var tblHeader = $('tr.boxheadrow').clone().addClass('repeated-header');

// Add the cloned header with the new class every 34th row (or as you see fit)
$('tbody tr:odd:nth-of-type(17n)').after(tblHeader);

// On the 'sortStart' routine, remove all the inserted header rows
$('#pmtable').bind('sortStart', function() {
    $('.repeated-header').remove();
    // On the 'sortEnd' routine, add back all the header row lines.
}).bind('sortEnd', function() {
    $('tbody tr:odd:nth-of-type(17n)').after(tblHeader);
});
0
DevlshOne
<html>
<head>
    <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
    <script>
        function stickyTableHead (tableID) {
            var $tmain = $(tableID);
            var $tScroll = $tmain.children("thead")
                .clone()
                .wrapAll('<table id="tScroll" />')
                .parent()
                .addClass($(tableID).attr("class"))
                .css("position", "fixed")
                .css("top", "0")
                .css("display", "none")
                .prependTo("#tMain");

            var pos = $tmain.offset().top + $tmain.find(">thead").height();


            $(document).scroll(function () {
                var dataScroll = $tScroll.data("scroll");
                dataScroll = dataScroll || false;
                if ($(this).scrollTop() >= pos) {
                    if (!dataScroll) {
                        $tScroll
                            .data("scroll", true)
                            .show()
                            .find("th").each(function () {
                                $(this).width($tmain.find(">thead>tr>th").eq($(this).index()).width());
                            });
                    }
                } else {
                    if (dataScroll) {
                        $tScroll
                            .data("scroll", false)
                            .hide()
                        ;
                    }
                }
            });
        }

        $(document).ready(function () {
            stickyTableHead('#tMain');
        });
    </script>
</head>

<body>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>

    <table id="tMain" >
        <thead>
        <tr>
            <th>1</th> <th>2</th><th>3</th> <th>4</th><th>5</th> <th>6</th><th>7</th> <th>8</th>

        </tr>
        </thead>
        <tbody>
            <tr><td>11111111111111111111111111111111111111111111111111111111</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
        </tbody>
    </table>
</body>
</html>
0
1.618

Irgendwie endete ich mit Position:Sticky in meinem Fall.

table{
  width: 100%;
  border: collapse;
}

th{
    position: sticky;
    top: 0px;
    border: 1px solid black;
    background: #ff5722;
    color: #f5f5f5;
    font-weight: 600;
}
td{
    background: #d3d3d3;
    border: 1px solid black;
    color: #f5f5f5;
    font-weight: 600;
}

div{
  height: 150px
  overflow: auto;
  width: 100%
}
<div>
    <table>
        <thead>
            <tr>
                <th>header 1</th>
                <th>header 2</th>
                <th>header 3</th>
                <th>header 4</th>
                <th>header 5</th>
                <th>header 6</th>
                <th>header 7</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
        </tbody>
    </table>
</div>

Verwenden Sie die neueste Version von jQuery und fügen Sie den folgenden JavaScript-Code hinzu.

$(window).scroll(function(){
  $("id of the div element").offset({top:$(window).scrollTop()});
});
0
Prabhavith

Ich wünschte, ich hätte @ Marks Lösung früher gefunden, aber ich habe meine eigene geschrieben, bevor ich diese SO -Frage sah ...

Mine ist ein sehr leichtes jQuery-Plugin, das feste Kopf- und Fußzeilen, Spaltenumbrüche (Colspan), Größenänderungen, horizontalen Bildlauf und eine optionale Anzahl von Zeilen unterstützt, die vor dem Bildlauf angezeigt werden.

jQuery.scrollTableBody (GitHub)

Solange Sie über eine Tabelle mit den richtigen Codes <thead>, <tbody> und (optional) <tfoot> verfügen, müssen Sie nur Folgendes tun:

$('table').scrollTableBody();
0
Noah Heldman