Tabelle mit festem Header und fester Spalte auf reinem CSS


97

Ich muss eine HTML-Tabelle (oder etwas ähnlich aussehendes) mit einem festen Header und einer festen ersten Spalte erstellen.

Jede Lösung, die ich bisher gesehen habe, verwendet Javascript oder jQueryzum Festlegen von scrollTop / scrollLeft, funktioniert jedoch in mobilen Browsern nicht reibungslos. Daher suche ich nach einer reinen CSS-Lösung.

Ich habe hier eine Lösung für eine feste Spalte gefunden: jsfiddle.net/C8Dtf/20/, aber ich weiß nicht, wie ich sie verbessern kann, um auch den Header zu reparieren .

Ich möchte, dass es in Webkit-Browsern funktioniert oder einige css3Funktionen verwendet, aber ich wiederhole, ich möchte es nicht Javascriptzum Scrollen verwenden.

BEARBEITEN: Dies ist ein Beispiel für das Verhalten, das ich erreichen möchte: https://web.archive.org/web/20130829032141/http://datatables.net/release-datatables/extras/FixedColumns/css_size.html


Ich sehe nicht, wo <html> <Tabelle> mit festem Header <thead> im Moment mit CSS-Level-3 zu tun hat. Was hast du noch ? Was hast du bisher versucht ?
Milche Patern

Ich habe versucht, komplexes positionVerhalten auf Zeilen und Zellen anzuwenden , aber ich verstehe nicht ganz, wo es anwendbar ist oder nicht.
Panfil

2
Diese Antwort kann Ihnen helfen stackackflow.com/questions/14834198/…
Garry

Antworten:


138

Eine echte reine CSS-Lösung mit einer festen Kopfzeile und einer ersten Spalte

Ich musste eine Tabelle mit einem festen Header und einer festen ersten Spalte mit reinem CSS erstellen, und keine der Antworten hier war genau das, was ich wollte.

Die position: stickyEigenschaft unterstützt sowohl das Festhalten an der Oberseite (wie ich am häufigsten gesehen habe) als auch an der Seite in modernen Versionen von Chrome, Firefox und Edge. Dies kann mit einem kombiniert werden div, das die overflow: scrollEigenschaft hat, Ihnen eine Tabelle mit festen Überschriften zu geben, die an einer beliebigen Stelle auf Ihrer Seite platziert werden kann:

Stellen Sie Ihren Tisch in einen Behälter:

<div class="container">
  <table></table>
</div>

Verwenden Sie overflow: scrollauf Ihrem Container, um das Scrollen zu aktivieren:

div.container {
  overflow: scroll;
}

Wie Dagmar in den Kommentaren betonte, benötigt der Container auch a max-widthund a max-height.

Verwenden position: stickyTabelle Zellen kleben an der Kante und top, rightoder leftzu wählen , die Kante zu Stick:

thead th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  top: 0;
}

tbody th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  left: 0;
}

Wie MarredCheese in den Kommentaren erwähnt hat, können Sie, wenn Ihre erste Spalte <td>Elemente anstelle von <th>Elementen enthält, diese tbody td:first-childin Ihrem CSS anstelle von verwendentbody th

Verwenden Sie Folgendes, damit die Überschrift in der ersten Spalte links bleibt:

thead th:first-child {
  left: 0;
  z-index: 1;
}

https://jsfiddle.net/qwubvg9m/1/


22
Dies scheint die beste Antwort zu sein.
user1190132

9
@ PirateApp Wenn Sie die widthIhrer ersten Spalte kennen, können Sie sie position: stickyfür die Zellen in Ihrer zweiten Spalte mit einem leftWert verwenden, der dem Ihrer ersten Spalte entspricht width: jsfiddle.net/wvypo83c/794
Matthew Schlachter

4
Diese Antwort beweist, dass es sich lohnt, ganz nach unten zu lesen!
Mlerley

4
Dies funktioniert nicht ohne eine am Container festgelegte maximale Breite und Höhe.
Dagmar

9
Diese Antwort ist ein Leuchtturm, der uns durch das endlose Meer von fehlerhaften, überkomplizierten und zeitraubenden Antworten von überraschend selbstbewussten, verwirrend hochgestuften Postern hier auf SO und im Internet nach Hause führt. Beachten Sie, dass Sie, wenn Ihre erste Spalte <td>Elemente anstelle von <th>Elementen enthält, diese tbody td:first-childin Ihrem CSS anstelle von verwenden können tbody th.
MarredCheese

32

Heutzutage ist dies nur mit Eigenschaft mit CSS möglich .position: sticky

Hier geht ein Ausschnitt:

(jsFiddle: https://jsfiddle.net/hbqzdzdt/5/ )

.grid-container {
  display: grid; /* This is a (hacky) way to make the .grid element size to fit its content */
  overflow: auto;
  height: 300px;
  width: 600px;
}
.grid {
  display: flex;
  flex-wrap: nowrap;
}
.grid-col {
  width: 150px;
  min-width: 150px;
}

.grid-item--header {
  height: 100px;
  min-height: 100px;
  position: sticky;
  position: -webkit-sticky;
  background: white;
  top: 0;
}

.grid-col--fixed-left {
  position: sticky;
  left: 0;
  z-index: 9998;
  background: white;
}
.grid-col--fixed-right {
  position: sticky;
  right: 0;
  z-index: 9998;
  background: white;
}

.grid-item {
  height: 50px;
  border: 1px solid gray;
}
<div class="grid-container">
  <div class="grid">
    <div class="grid-col grid-col--fixed-left">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col grid-col--fixed-right">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
    </div>

  </div>
</div>

In Bezug auf die Kompatibilität. Es funktioniert in allen gängigen Browsern, jedoch nicht im IE. Es gibt eine Polyfüllung für, position: stickyaber ich habe es nie versucht.


2
Das ist großartig, ich liebe es!
Kapitän Lu

3
Wie auch immer, dies mit <table> -Tags und nicht mit <div> zu erreichen
Andreas

1
Ich denke, dies wird keine gute Leistung bringen, wenn Sie eine Anwendung entwickeln und Datensätze durchlaufen müssen, um diese Tabelle zu drucken, da Sie für jede Spalte in der Tabelle das gesamte Array des Datensatzes durchlaufen müssen. Dieser HTML-Code arbeitet spaltenweise.
Igasparetto

@igasparetto Sie können die Zeilen / Spalten tatsächlich umgekehrt anordnen, und die Lösung würde weiterhin funktionieren. Wenn ich etwas Zeit später habe, kann ich ein Snippet mit der Rasterreihenfolge -> Spalte erstellen.
Alvaro

2
Ich würde davon abraten, tabellarische Daten ohne Verwendung von <table> und zugehörigen Tags anzuzeigen. Es gibt verschiedene Probleme, die beabsichtigte Verwendung von HTML auf diese Weise zu unterbrechen, einschließlich der Barrierefreiheit. Siehe auch: w3.org/WAI/tutorials/tables
Ben Morris

15

Das ist keine leichte Aufgabe.

Der folgende Link führt zu einer funktionierenden Demo:

Link Aktualisiert gemäß dem Kommentar von lanoxx

http://jsfiddle.net/C8Dtf/366/

Denken Sie daran, diese hinzuzufügen:

<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/media/js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/media/js/jquery.dataTables.js"></script>
<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/extras/FixedColumns/media/js/FixedColumns.js"></script>

Ich sehe keinen anderen Weg, dies zu erreichen. Vor allem nicht nur mit CSS.

Das ist viel zu durchmachen. Hoffe das hilft :)


Um den Filter "bFilter": false
auszuschalten,

6
Es ist möglich , dies nur mit CSS zu erreichen. Nicht einfach aber möglich.
Jimmy T.

Von ungefähr 10 Lösungen war dies die einzige, die funktionierte. Übrigens, um das "Anzeigen von 1 bis 57 von 57 Einträgen" zu entfernen, fügen Sie es "bInfo" : falsein den .dataTable()Aufruf ein
hansaplast

datatables == "awesome"
billynoah

Downvoting dieser Lösung, weil es schlecht ist. Das theadbefindet sich in einer eigenen Tabelle, die nicht an Änderungen von tdElementen gebunden ist. Wenn also ein Zellentext lang ist, wird die thBreite nicht entsprechend angepasst.
vsync

14

Alle diese Vorschläge sind großartig und alle, aber sie reparieren entweder nur den Header oder eine Spalte, nicht beide, oder sie verwenden Javascript. Der Grund - es glaubt nicht, dass es in reinem CSS gemacht werden kann. Der Grund:

Wenn dies möglich wäre, müssten Sie mehrere scrollbare Divs ineinander verschachteln, die jeweils einen Scroll in eine andere Richtung aufweisen. Dann müssten Sie Ihre Tabelle in drei Teile aufteilen - den festen Header, die feste Spalte und den Rest der Daten.

Fein. Aber jetzt das Problem - Sie können dafür sorgen, dass einer von ihnen beim Scrollen in Position bleibt, der andere befindet sich jedoch im Bildlaufbereich von first und kann daher selbst außer Sichtweite gescrollt werden, sodass er nicht fixiert werden kann der Bildschirm. "Ah-ha", sagst du, "aber ich kann irgendwie die absolute oder feste Position verwenden, um das zu tun" - nein, das kannst du nicht. Sobald Sie dies tun, verlieren Sie die Fähigkeit, diesen Container zu scrollen. Es ist eine Henne-Ei-Situation - man kann nicht beide haben, sie heben sich gegenseitig auf.

Ich glaube, die einzige Lösung ist Javascript. Sie müssen die drei Elemente vollständig trennen und ihre Positionen durch Javascript synchron halten. Es gibt gute Beispiele in anderen Beiträgen auf dieser Seite. Dieser ist auch einen Blick wert:

http://tympanus.net/codrops/2014/01/09/sticky-table-headers-columns/


9

Ich habe einige Änderungen in jsfiddle vorgenommen. Dies könnte das sein, was Sie versuchen zu tun.

http://jsfiddle.net/C8Dtf/81/

Ich habe die Titel so fest codiert:

<table id="left_table" class="freeze_table">
    <tr class='tblTitle'>
         <th>Title 1</th>
         <th>Title 2</th>
    </tr>
</table>

Und ich habe auch einige Stile hinzugefügt.

.tblTitle{
   position:absolute;
    top:0px;
    margin-bottom:30px;
    background:lightblue;
}
td, th{
    padding:5px;
    height:40px;
    width:40px;
    font-size:14px;
}

Hoffe das ist was du willst :)


1
Ich brauche eine Kopfzeile der rechten Tabelle, um zusammen mit ihrem Inhalt zu scrollen.
Panfil

Hier ist die URL: jsfiddle.net/C8Dtf/84 . Sie müssen nur mit dem Styling für den rechten Tisch herumspielen, um die beiden Tische auszurichten.
Phillip-Juan

Nein, du verstehst nicht ganz. Ich brauche die Kopfzeile der rechten Tabelle oben zu fixieren, damit sie immer noch sichtbar ist, wenn die Tabelle nach oben und unten rollt, aber wenn die Tabelle nach rechts oder links rollt, muss die Kopfzeile nach rechts oder links scrollen, aber immer noch oben fixiert sein. Entschuldigen Sie meine schlechten Englischkenntnisse.
Panfil

Möchten Sie also, dass die Kopfzeile der rechten Tabelle beim vertikalen Scrollen und beim horizontalen Scrollen fixiert wird?
Phillip-Juan

Dies ist ein Beispiel für das Verhalten, das ich erreichen möchte: datatables.net/release-datatables/extras/FixedColumns/…
panfil

9

Ein Beispiel, das nur CSS verwendet:

.table {
  table-layout: fixed;
  width: 500px;
  border-collapse: collapse;
}

.header th {
  font-family: Calibri;
  font-size: small;
  font-weight: lighter;
  border-left: 1px solid #000;
  background: #d0d0d0;
}

.body_panel {
  display: inline-block;
  width: 520px;
  height: 300px;
  overflow-y: scroll;
}

.body tr {
  border-bottom: 1px solid #d0d0d0;
}

.body td {
  border-left: 1px solid #d0d0d0;
  padding-left: 3px;
  font-family: Calibri;
  font-size: small;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
<body>

  <table class="table">

    <thead class="header">

      <tr>
        <th style="width:20%;">teste</th>
        <th style="width:30%;">teste 2</th>
        <th style="width:50%;">teste 3</th>
      </tr>

    </thead>
  </table>

  <div class="body_panel">

    <table class="table">
      <tbody class="body">

        <tr>
          <td style="width:20%;">asbkj k kajsb ksb kabkb</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

      </tbody>
    </table>

  </div>

</body>


3
Ich musste nicht nur heder reparieren, sondern auch die erste Spalte.
Panfil

Dieses Beispiel zeigt einen Ansatz mit zwei Tabellen im HTML-Code: Eine Tabelle rendert nur den Header. Die zweite Tabelle rendert nur die Zeilen, jedoch innerhalb von a div. Es ist die div, die die Zeilen Scrollen während des Header bleibt an der gleichen Stelle erlaubt. Dieser Ansatz funktionierte für meine Bedürfnisse.
David Tansey

Wenn auch horizontal gescrollt wird, benötigen Sie JS, um die Bildlaufpositionen der Tabellen zu synchronisieren.
Zoltán Tamási

4

Um sowohl Kopfzeilen als auch Spalten zu reparieren, können Sie das folgende Plugin verwenden:


Aktualisiert im Juli 2019

Kürzlich wurde auch eine reine CSS-Lösung entwickelt , die auf der CSS-Eigenschaft position: sticky;( hier für weitere Details) basiert und auf jedes THElement (anstelle des übergeordneten Containers) angewendet wird.


1
Der erste Link ist unterbrochen. Zweitens verwendet man jQuery.
PussInBoots

Aktualisierte Antwort, um toten Link zu entfernen
Luca Detomi

3

Ich habe eine ausgezeichnete Lösung von Paul O'Brien für das Problem gefunden und möchte den Link teilen: https://codepen.io/paulobrien/pen/LBrMxa

Ich habe den Stil für die Fußzeile entfernt:

html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
.intro {
  max-width: 1280px;
  margin: 1em auto;
}
.table-scroll {
  position: relative;
  width:100%;
  z-index: 1;
  margin: auto;
  overflow: auto;
  height: 350px;
}
.table-scroll table {
  width: 100%;
  min-width: 1280px;
  margin: auto;
  border-collapse: separate;
  border-spacing: 0;
}
.table-wrap {
  position: relative;
}
.table-scroll th,
.table-scroll td {
  padding: 5px 10px;
  border: 1px solid #000;
}
.table-scroll thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
}

th:first-child {
  position: -webkit-sticky;
  position: sticky;
  left: 0;
  z-index: 2;
  background: #ccc;
}
thead th:first-child {
  z-index: 5;
}

2

Ich musste kürzlich eine Lösung mit einer festen Kopfgruppe und einer festen ersten Spalte erstellen. Ich teilte meine Tabelle in divs auf und verwendete jquery, um das Scrollen im Fenster zu erfassen.

http://jsfiddle.net/TinT/EzXub/2346/

var prevTop = 0;
var prevLeft = 0;

$(window).scroll(function(event){
  var currentTop = $(this).scrollTop();
  var currentLeft = $(this).scrollLeft();

  if(prevLeft !== currentLeft) {
    prevLeft = currentLeft;
    $('.header').css({'left': -$(this).scrollLeft()})
  }
  if(prevTop !== currentTop) {
    prevTop = currentTop;
    $('.leftCol').css({'top': -$(this).scrollTop() + 40})
  }
});

1

Ein Mitarbeiter und ich haben gerade ein neues GitHub-Projekt veröffentlicht, das eine Angular-Direktive enthält, mit der Sie Ihre Tabelle mit festen Überschriften dekorieren können: https://github.com/objectcomputing/FixedHeader

Es basiert nur auf CSS und Angular, mit einer Direktive, die einige Divs hinzufügt. Es ist keine jQuery erforderlich.

Diese Implementierung ist nicht so umfassend wie einige andere Implementierungen. Wenn Sie jedoch lediglich feste Tabellen hinzufügen möchten, ist dies möglicherweise eine gute Option.


1

Nach zwei Tagen Kampf mit Internet Explorer 9 + Chrome + Firefox (Windows) und Safari (Mac) habe ich ein System gefunden, das ist

  • Kompatibel mit all diesen Browsern
  • Ohne Javascript zu verwenden
  • Verwenden Sie nur une div und eine Tabelle
  • Kopf- und Fußzeile (außer IE) mit scrollbarem Text korrigiert. Kopfzeile und Textkörper mit gleichen Spaltenbreiten

Ergebnis: Geben Sie hier die Bildbeschreibung ein

HTML:

  <thead>
    <tr>
      <th class="nombre"><%= f.label :cost_center %></th>
      <th class="cabecera cc">Personal</th>
      <th class="cabecera cc">Dpto</th>
    </tr>
  </thead>
  <tbody>
    <% @cost_centers.each do |cc| %>
    <tr>
      <td class="nombre"><%= cc.nombre_corto %></td>
      <td class="cc"><%= cc.cacentrocoste %></td>
      <td class="cc"><%= cc.cacentrocoste_dpto %></td>
    </tr>
    <% end %>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="3"><a href="#">Mostrar mas usuarios</a></td>
    </tr>
  </tfoot>
</table>

CSS:

div.cost_center{
  width:320px;
  font-size:75%;
  margin-left:5px;
  margin-top:5px;
  margin-bottom: 2px;
  float: right;
  display: inline-block;
  overflow-y: auto;
  overflow-x: hidden;
  max-height:300px;  
}

div.cost_center label { 
  float:none;
  font-size:14px;
}

div.cost_center table{
  width:300px;
  border-collapse: collapse; 
  float:right;
  table-layout:fixed;
}

div.cost_center table tr{
  height:16px;
}
div.cost_center th{
  font-weight:normal;
}

div.cost_center table tbody{
  display: block;
  overflow: auto;
  max-height:240px;
}

div.cost_center table thead{
  display:block;
}

div.cost_center table tfoot{
  display:block;
}
div.cost_center table tfoot td{
  width:280px;
}
div.cost_center .cc{
  width:60px;
  text-align: center; 
  border: 1px solid #999;
}

div.cost_center .nombre{
  width:150px;
}
div.cost_center tbody .nombre{
  border: 1px solid #999;
}

div.cost_center table tfoot td{
 text-align:center;  
 border: 1px solid #999; 
} 

div.cost_center table th, 
div.cost_center table td { 
  padding: 2px;
  vertical-align: middle; 
}

div.cost_center table tbody td {
  white-space: normal;
  font:  .8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: white;
}
div.cost_center table th.cabecera { 
  font:  0.8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: #FFEAB5;
}

Guter Versuch, funktioniert aber nicht so gut für mich. In diesem Beispiel ( jsfiddle.net/5ka6e ) wird die Größe des Headers nicht korrekt geändert . Diese Art von Fehler kann schließlich dazu führen, dass Daten und Header nicht übereinstimmen.
Darkzangel

1
Sie vergessen, hinzuzufügen, div.cost_center table{border-collapse: collapse;}und die dritte Beschriftung muss etwas sein, das in die 60px (in diesem Beispiel) passt
Albert Català

1

Die vorhandenen Antworten passen zu den meisten Menschen, aber für diejenigen, die Schatten unter der festen Überschrift und rechts von der ersten (festen) Spalte hinzufügen möchten , ist hier ein Arbeitsbeispiel (reines CSS):

http://jsbin.com/nayifepaxo/1/edit?html,output

Der wichtigste Trick dies zu Arbeit in immer wird mit ::afterSchatten rechts von jedem der ersten hinzuzufügen tdin jedem tr:

tr td:first-child:after {
  box-shadow: 15px 0 15px -15px rgba(0, 0, 0, 0.05) inset;
  content: "";
  position:absolute;
  top:0;
  bottom:0;
  right:-15px;
  width:15px;
}

Ich habe eine Weile gebraucht (zu lange ...), um alles zum Laufen zu bringen, also dachte ich mir, ich würde es für diejenigen teilen, die sich in einer ähnlichen Situation befinden.


Haben Sie dies auf eine andere Antwort gestützt und den Schatten hinzugefügt?
PussInBoots

1

Kopfzeile müssen korrigiert werden


0

So etwas könnte für Sie funktionieren ... Es wird wahrscheinlich erforderlich sein, dass Sie Spaltenbreiten für Ihre Kopfzeile festgelegt haben.

thead { 
    position: fixed;
}

http://jsfiddle.net/vkhNC/

Aktualisieren:

Ich bin nicht davon überzeugt, dass das von Ihnen gegebene Beispiel nur mit CSS möglich ist. Ich würde es lieben, wenn jemand mir das Gegenteil beweisen würde. Folgendes habe ich bisher . Es ist nicht das fertige Produkt, aber es könnte ein Anfang für Sie sein. Ich hoffe, dies weist Sie in eine hilfreiche Richtung, wo immer das auch sein mag.


Ich brauche nicht nur den Header, sondern auch die erste Spalte.
Panfil

5
Das Problem ist, dass Header ihre Breite verlieren. Es sieht hässlich aus mit unterschiedlichen Header-Spaltengrößen und Datenspaltengrößen.
Akash Kava


0

Beispiel für reines CSS:

<div id="cntnr">
    <div class="tableHeader">
        <table class="table-header table table-striped table-bordered">
            <thead>
                <tr>
                    <th>this</th>
                    <th>transmission</th>
                    <th>is</th>
                    <th>coming</th>
                    <th>to</th>
                    <th>you</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                </tr>
            </tbody>
        </table>
    </div>


    <div class="tableBody">
        <table class="table-body table table-striped table-bordered">
            <thead>
                <tr>
                    <th>this</th>
                    <th>transmission</th>
                    <th>is</th>
                    <th>coming</th>
                    <th>to</th>
                    <th>you</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                </tr>
            </tbody>
        </table>
    </div>

</div>

#cntnr {
    width: auto;
    height: 200px;
    border: solid 1px #444;
    overflow: auto;
}

.tableHeader {
    position: fixed;
    height: 40px;
    overflow: hidden;
    margin-right: 18px;
    background: white;
}

.table-header tbody {
    height: 0;
    visibility: hidden;
}

.table-body thead {
    height: 0;
    visibility: hidden;
}

http://jsfiddle.net/cCarlson/L98m854d/

Nachteil: Die feste Header-Struktur / Logik hängt ziemlich stark von bestimmten Dimensionen ab, sodass Abstraktion wahrscheinlich keine praktikable Option ist .


Benötigen Sie sowohl feste Überschrift als auch feste erste Spalte.
Panfil

Ah ... danke, dass du darauf hingewiesen hast, Panfil. Ich werde eine Bearbeitung vornehmen. Prost
Cody

0

Position: Sticky funktioniert nicht für einige Elemente wie (Thead) in Chrome und andere Webkit-Browser wie Safari.

Aber es funktioniert gut mit (th)

body {
  background-color: rgba(0, 255, 200, 0.1);
}

.intro {
  color: rgb(228, 23, 23);
}

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

.sticky {
  position: sticky;
  top: 0;
  color: black;
  background-color: white;
}
<div class="container intro">
  <h1>Sticky Table Header</h1>
  <p>Postion : sticky doesn't work for some elements like (thead) in chrome and other webkit browsers like safari. </p>
  <p>But it works fine with (th)</p>
</div>
<div class="container wrapper">
  <table class="table table-striped">
    <thead>
      <tr>
        <th class="sticky">Firstname</th>
        <th class="sticky">Lastname</th>
        <th class="sticky">Email</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>James</td>
        <td>Vince</td>
        <td>james@example.com</td>
      </tr>
      <tr>
        <td>Jonny</td>
        <td>Bairstow</td>
        <td>jonny@example.com</td>
      </tr>
      <tr>
        <td>James</td>
        <td>Anderson</td>
        <td>james@example.com</td>
      </tr>
      <tr>
        <td>Stuart</td>
        <td>Broad</td>
        <td>stuart@example.com</td>
      </tr>
      <tr>
        <td>Eoin</td>
        <td>Morgan</td>
        <td>eoin@example.com</td>
      </tr>
      <tr>
        <td>Joe</td>
        <td>Root</td>
        <td>joe@example.com</td>
      </tr>
      <tr>
        <td>Chris</td>
        <td>Woakes</td>
        <td>chris@example.com</td>
      </tr>
      <tr>
        <td>Liam</td>
        <td>PLunkett</td>
        <td>liam@example.com</td>
      </tr>
      <tr>
        <td>Jason</td>
        <td>Roy</td>
        <td>jason@example.com</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Hales</td>
        <td>alex@example.com</td>
      </tr>
      <tr>
        <td>Jos</td>
        <td>Buttler</td>
        <td>jos@example.com</td>
      </tr>
      <tr>
        <td>Ben</td>
        <td>Stokes</td>
        <td>ben@example.com</td>
      </tr>
      <tr>
        <td>Jofra</td>
        <td>Archer</td>
        <td>jofra@example.com</td>
      </tr>
      <tr>
        <td>Mitchell</td>
        <td>Starc</td>
        <td>mitchell@example.com</td>
      </tr>
      <tr>
        <td>Aaron</td>
        <td>Finch</td>
        <td>aaron@example.com</td>
      </tr>
      <tr>
        <td>David</td>
        <td>Warner</td>
        <td>david@example.com</td>
      </tr>
      <tr>
        <td>Steve</td>
        <td>Smith</td>
        <td>steve@example.com</td>
      </tr>
      <tr>
        <td>Glenn</td>
        <td>Maxwell</td>
        <td>glenn@example.com</td>
      </tr>
      <tr>
        <td>Marcus</td>
        <td>Stoinis</td>
        <td>marcus@example.com</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Carey</td>
        <td>alex@example.com</td>
      </tr>
      <tr>
        <td>Nathan</td>
        <td>Coulter Nile</td>
        <td>nathan@example.com</td>
      </tr>
      <tr>
        <td>Pat</td>
        <td>Cummins</td>
        <td>pat@example.com</td>
      </tr>
      <tr>
        <td>Adam</td>
        <td>Zampa</td>
        <td>zampa@example.com</td>
      </tr>
    </tbody>
  </table>
</div>

Oder besuchen Sie mein Codepen-Beispiel :



-2

Wenn Sie nur reines HTML und CSS verwenden möchten, habe ich eine Lösung für Ihr Problem:
In dieser jsFiddle sehen Sie eine Nicht-Skript-Lösung, die eine Tabelle mit einem festen Header bereitstellt. Es sollte kein Problem sein, das Markup auch für eine feste erste Spalte anzupassen. Sie müssten nur eine absolut positionierte Tabelle für die erste Spalte innerhalb von hWrapper-div erstellen und -div neu vWrapperpositionieren.
Das Bereitstellen von dynamischem Inhalt sollte mit serverseitigen oder browser-seitigen Versuchungsmodulen kein Problem darstellen. Meine Lösung funktioniert in allen modernen Browsern und älteren Browsern ab IE8 gut.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.