CSS Tabelle mit scrollbaren Body

jb_alvarado

Lieutenant
Registriert
Sep. 2015
Beiträge
592
Hallo allerseits,
wollte mal fragen wie ihr das Problem lösen würdet:

Ich möchte eine Tabelle erzeugen, die beliebig viele Zeilen hat, deshalb soll sie Scrollbar sein. Ich möchte allerdings den Header fest haben, so dass nur der Body gescrollt wird. Die gängige Methode ist, was man so ließt, von Head und Body das display Attribut auf block zu stellen. Das erzielt bei mir allerdings nicht das gewünschte Ergebnis. Meine Tabelle soll in etwa so aufgebaut sein:

Code:
Start    | File                      | Play | Duration | In       | Out      | Ad | Edit | Delete
-------------------------------------------------------------------------------------------------
00:00:00 | long_filename.mp4         |  *   | 00:30:00 | 00:00:00 | 00:30:00 | -  |   #  |   x

Wichtig ist mir, dass hier die Spalte File eine variable Breite hat und alle anderen Spalten sollen nur so breit wie der Inhalt ist. Wenn ich wie über google vorgeschlagen display auf block stelle funktioniert das mit der Breite nicht mehr wie gewünscht, sondern es hätten alle Spalten die gleiche Breite.

Normalerweise würde ich das mit einem grid machen, alle Breiten fest vergeben und der File Spalte 100% geben. Das geht aber in meinem Fall nicht, weil ich das Programm mehrsprachig anbiete und Benutzer auf Github dann weitere Sprachen hinzufügen können. Dadurch weiß ich nicht wie breit die einzelnen Spalten in der Zukunft sein müssen. Ein Beispiel ist schon der Unterschied zwischen Deutsch und Englisch, da hätte so einen Unterschied:


Code:
# Englisch
... | In       | Out      | Ad | ...

# Deutsch
... | Eingang  | Ausgang  | Werbung | ...
... | 00:00:00 | 00:30:00 |    -    | ...

In/Out finde ich ok, aber der Unterschied zwischen Ad und Werbung ist mir schon zu groß und ich weiß ja nicht wie das mit anderen Sprachen sein wird. Brauchen die noch mehr Platz, oder weniger?

Eine Tabelle ist hier schon am besten, wenn sie kein display block hat und ich die File Spalte auf 100% Breite stelle, verhält sie sich so wie ich das möchte.

Fallen euch noch Möglichkeiten ein, wie ich das lösen könnte?
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: netzgestaltung
Ich danke euch für die Ansätze! position-sticky für den Tabellen-Header wäre fast das richtige. Allerdings verträgt sich das komischerweise nicht mit einer variablen Breite einer Spalten. Das geht nur richtig wenn ich keine Breiten vergebe, aber dann sind alle Spalten wieder gleich breit.

Das Problem bei dem Grid ist noch, dass ich das Grid nicht auf das gesamte "Tabellenkonstrukt" anwenden kann. Hatte im Eingangspost hier vielleicht noch die Info vergessen, dass auch das Befüllen des Inhaltes nicht fest ist, sondern erst bei der Nutzung gefüllt wird. Zudem ist jede Zeile verschiebar. Hier mal ein Bild, wie das aussieht.

Der generierte Code schaut dann in etwa so aus:

HTML:
<!-- HEADER -->
<div class="grid grid-cols-[70px_auto_75px_70px_70px] md:grid-cols-[70px_auto_75px_70px_70px_70px_70px_80px_60px]">
    <div class="px-3 py-2">Start</div>
    <div class="px-3 py-2">Datei</div>
    <div class="px-3 py-2 text-center">Abspielen</div>
    <div class="px-3 py-2">Dauer</div>
    <div class="px-3 py-2 hidden md:flex">Eingang</div>
    <div class="px-3 py-2 hidden md:flex">Ausgang</div>
    <div class="px-3 py-2 hidden md:flex justify-center">Werbung</div>
    <div class="px-3 py-2 text-center">Bearbeiten</div>
    <div class="px-3 py-2 hidden md:flex justify-center">Löschen</div>
</div>
<div id="scroll-container" class="h-[calc(100%-44px)] overflow-auto">
    <!-- BODY -->
    <ul class="" style="height: 5206px">
        <li
            id="clip_0"
            class="draggable grid grid-cols-[70px_auto_75px_70px_70px] md:grid-cols-[70px_auto_75px_70px_70px_70px_70px_80px_60px] h-[38px] bg-lime-500/30"
        >
            <div class="px-3 py-2">05:59:25</div>
            <div class="px-3 py-2 truncate grabbing cursor-grab">clip_1.mp4</div>
            <div class="px-3 py-2 text-center">
                <button><i class="bi-play-fill"></i></button>
            </div>
            <div class="px-3 py-2">00:11:12</div>
            <div class="px-3 py-2 hidden md:flex">00:00:00</div>
            <div class="px-3 py-2 hidden md:flex">00:11:12</div>
            <div class="px-3 py-[11px] hidden md:flex justify-center">
                <input class="checkbox checkbox-xs rounded" type="checkbox" />
            </div>
            <div class="px-3 py-2 text-center">
                <button><i class="bi-pencil-square"></i></button>
            </div>
            <div class="px-3 py-2 text-center hidden md:flex justify-center hover:text-base-content/70">
                <button><i class="bi-x-circle-fill"></i></button>
            </div>
        </li>
        <li
            id="clip_1"
            class="draggable grid grid-cols-[70px_auto_75px_70px_70px] md:grid-cols-[70px_auto_75px_70px_70px_70px_70px_80px_60px] h-[38px] bg-base-300 even:bg-base-100"
        >
            <div class="px-3 py-2">06:10:37</div>
            <div class="px-3 py-2 truncate grabbing cursor-grab">clip_2.mp4</div>
            <div class="px-3 py-2 text-center">
                <button><i class="bi-play-fill"></i></button>
            </div>
            <div class="px-3 py-2">00:03:59</div>
            <div class="px-3 py-2 hidden md:flex">00:00:00</div>
            <div class="px-3 py-2 hidden md:flex">00:03:59</div>
            <div class="px-3 py-[11px] hidden md:flex justify-center">
                <input class="checkbox checkbox-xs rounded" type="checkbox" />
            </div>
            <div class="px-3 py-2 text-center">
                <button><i class="bi-pencil-square"></i></button>
            </div>
            <div class="px-3 py-2 text-center hidden md:flex justify-center hover:text-base-content/70">
                <button><i class="bi-x-circle-fill"></i></button>
            </div>
        </li>

        <!-- [...] -->

        <li
            id="clip_135"
            class="draggable grid grid-cols-[70px_auto_75px_70px_70px] md:grid-cols-[70px_auto_75px_70px_70px_70px_70px_80px_60px] h-[38px] bg-base-300 even:bg-base-100"
        >
            <div class="px-3 py-2">05:59:23</div>
            <div class="px-3 py-2 truncate grabbing cursor-grab">clip_136.mp4</div>
            <div class="px-3 py-2 text-center">
                <button><i class="bi-play-fill"></i></button>
            </div>
            <div class="px-3 py-2">00:01:00</div>
            <div class="px-3 py-2 hidden md:flex">00:00:00</div>
            <div class="px-3 py-2 hidden md:flex">00:00:02</div>
            <div class="px-3 py-[11px] hidden md:flex justify-center">
                <input class="checkbox checkbox-xs rounded" type="checkbox" />
            </div>
            <div class="px-3 py-2 text-center">
                <button><i class="bi-pencil-square"></i></button>
            </div>
            <div class="px-3 py-2 text-center hidden md:flex justify-center hover:text-base-content/70">
                <button><i class="bi-x-circle-fill"></i></button>
            </div>
        </li>
    </ul>
</div>
 
jb_alvarado schrieb:
Das geht nur richtig wenn ich keine Breiten vergebe, aber dann sind alle Spalten wieder gleich breit.
Das kann ich nicht rekonstruieren.
jb_alvarado schrieb:
Das Problem bei dem Grid ist noch, dass ich das Grid nicht auf das gesamte "Tabellenkonstrukt" anwenden kann. Hatte im Eingangspost hier vielleicht noch die Info vergessen, dass auch das Befüllen des Inhaltes nicht fest ist, sondern erst bei der Nutzung gefüllt wird.
Da sehe ich kein Problem. Du könntest das Konstrukt sogar als Tabelle mit <table>, <thead>, <tbody> etc. aufbauen und das Styling dann rein per CSS vornehmen ala:

CSS:
table
{
    display: grid;
}

thead, tbody
{
    display: contents;
}
 
  • Gefällt mir
Reaktionen: Der Lord
Ah so, mein Vorschlag bezog sich auf eine native Tabelle mit sauberem Aufbau thead, tbody und tfoot und nicht eine Div Suppe :rolleyes:
Ich habe auch Spalten mit fixen und variablen Breiten, geht eigentlich alles. Es funktioniert sogar mit colspan und rowspan querbeet gemischt.
 
@Lawnmower, in meinem Eingangspost ging ich schon auch von einer normalen Tabelle aus, das div Grid wäre nur einen zweiter Ansatz.

Wenn ich das mit den Breiten hinbekommen, nehme ich gerne die Standardtabelle.

Tabelle mit grid/contents CSS kannte ich so noch nicht, versuche ich auch gerade, aber aktuell ist das die Spaltenbreite noch nicht korrekt.
 
Also Tabelle mit grid/contents Layout funktioniert nicht, weil dann das Drag&Drop/Move Event nicht mehr richtig funktioniert.

Und Sticky Header geht nur bedingt. Hier mal ein Beispiel Code:


HTML:
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            .container {
                height: 50px;
                overflow: auto;
            }
            table,
            th,
            td {
                border: 1px solid black;
                border-collapse: collapse;
                padding: 4px 6px 4px 6px;
            }

            /*  table {
                width: 100%;
                table-layout: fixed;
            }

            thead {
                position: sticky;  
                top: 0;
            }  */

            .fit-content {
                width: 1%;
                white-space: nowrap;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <table>
                <thead>
                    <tr>
                        <th class="fit-content">Start</th>
                        <th class="expand">Datei</th>
                        <th class="fit-content">Abspielen</th>
                        <th class="fit-content">Dauer</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>00:00:00</td>
                        <td>file_1.mp4</td>
                        <td>-</td>
                        <td>00:30:00</td>
                    </tr>
                    <tr>
                        <td>00:30:00</td>
                        <td>file_2.mp4</td>
                        <td>-</td>
                        <td>00:20:00</td>
                    </tr>
                    <tr>
                        <td>00:50:00</td>
                        <td>file_3.mp4</td>
                        <td>-</td>
                        <td>00:20:00</td>
                    </tr>
                </tbody>
            </table>
        </div>
       
    </body>
</html>

So hätten meine Spalten die gewünschte Breite. Wenn ich allerdings die Methode mit dem Sticky Header anwende funktioniert es nicht mehr.
 
Habe den Sticky bei mir auf dem thead tr td und nicht auf dem thead (kA ob das was ausmacht).
CSS:
thead tr th
{   
    position: sticky;
    top: 0;
    z-index: 10;
}
 
wilk84 schrieb:
Das macht überhaupt keinen Sinn, was du da schreibst und gelesen hast.
Das mag sein, wenn man nach "html table scrollable body" sucht bekommt man mehrere Ergebnisse gleich auf der ersten Seite die das Vorschlagen. Vielleicht war das vor der Unterstützung von position: sticky; die geläufige Methode.

Dein Beispiel geht in die richtige Richtung, allerdings ergibt sich damit auch ein Problem welches ich noch nicht lösen konnte: Wenn ich einen langen Dateinamen habe lässt sich die Tabelle nicht richtig in der Breite stauchen. Und ich habe es nicht hinbekommen auf die dehnbare Spalte dieses CSS anzuwenden:

CSS:
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

Mit table-layout: fixed; funktionieren die CSS Regeln, aber da muss ich wieder die Spaltenbreite definieren.
 
Ich hatte kürzlich auch Probleme mit dem Layout einer <table> und hab es letztlich dann komplett mit CSS Grid gelöst (ganz ohne <table>). Mir ist aus deinen Kommentaren nicht ganz klar, was genau an CSS Grid bei dir nicht funktioniert hat. Du sagst z.B., man müsse alle Breiten fest eingeben, aber dafür gibt es ja Spezialwerte wie "max-content".
 
Zurück
Oben