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

panfil
quelle
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/

Matthew Schlachter
quelle
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.

Alvaro
quelle
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 :)

Phillip-Juan
quelle
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/

PretorianNZ
quelle
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 :)

Phillip-Juan
quelle
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>

Dyego.JhOu
quelle
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.

Luca Detomi
quelle
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;
}
Artiom Kozyrev
quelle
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})
  }
});
Tristan
quelle
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.

user3221325
quelle
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;
}
Albert Català
quelle
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.


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

Kopfzeile müssen korrigiert werden

neel upadhyay
quelle
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.

Bradj
quelle
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

Eine andere Lösung ist die Verwendung von AngularJS. Das AngularUI-Modul verfügt über eine Direktive namens ng-grid, die eine Funktion namens Column Pinning unterstützt. Es ist kein 100% reines CSS, aber auch nicht die anderen Lösungen.

http://angular-ui.github.io/ng-grid/#columnPinning

Lanoxx
quelle
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 .

Cody
quelle
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>[email protected]</td>
      </tr>
      <tr>
        <td>Jonny</td>
        <td>Bairstow</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>James</td>
        <td>Anderson</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Stuart</td>
        <td>Broad</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Eoin</td>
        <td>Morgan</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Joe</td>
        <td>Root</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Chris</td>
        <td>Woakes</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Liam</td>
        <td>PLunkett</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Jason</td>
        <td>Roy</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Hales</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Jos</td>
        <td>Buttler</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Ben</td>
        <td>Stokes</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Jofra</td>
        <td>Archer</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Mitchell</td>
        <td>Starc</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Aaron</td>
        <td>Finch</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>David</td>
        <td>Warner</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Steve</td>
        <td>Smith</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Glenn</td>
        <td>Maxwell</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Marcus</td>
        <td>Stoinis</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Carey</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Nathan</td>
        <td>Coulter Nile</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Pat</td>
        <td>Cummins</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Adam</td>
        <td>Zampa</td>
        <td>[email protected]</td>
      </tr>
    </tbody>
  </table>
</div>

Oder besuchen Sie mein Codepen-Beispiel :

Yoga
quelle
-1

Ich denke, das wird Ihnen helfen: https://datatables.net/release-datatables/extensions/FixedHeader/examples/header_footer.html

Kurz gesagt, wenn Sie wissen, wie eine Datentabelle erstellt wird, müssen Sie nur diese jQuery-Zeile ganz unten hinzufügen:

$(document).ready(function() {
    var table = $('#example').DataTable();

    new $.fn.dataTable.FixedHeader( table, {
        bottom: true
    } );
} );

bottom: true // dient dazu, den Bottom-Header ebenfalls zu fixieren.

Jack Sparrow
quelle
-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.

Lukas Hechenberger
quelle
-2

Müssen nur den Stil ändern als

<table style="position: relative;">
   <thead>
      <thead>
        <tr>
           <th></th>
        </tr>
      </thead>
   </thead>
   <tbody style="position: absolute;height: 300px;overflow:auto;">
      <tr>
         <td></td>
      </tr>
   </tbody>
</table>

Demo: https://plnkr.co/edit/Qxy5RMJBXmkaJAOjBtQn?p=preview

Omprakash Sharma
quelle
2
In Ihrer Demo ist die erste Spalte nicht festgelegt
Bravo