Machen Sie TBODY in Webkit-Browsern scrollbar

70

Ich bin mir dieser Frage bewusst , aber keine der Antworten funktioniert in Safari, Chrome usw.

Die akzeptierte Strategie ( wie hier gezeigt ) besteht darin, die Körperhöhe und die Überlaufeigenschaften wie folgt einzustellen:

<table>
    <thead>
        <tr><th>This is the header and doesn't scroll</th></tr>
    </thead>
    <tbody style="height:100px; overflow:auto;">
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
    </tbody>
</table>

Leider funktioniert dies in keinem Webkit-Browser. Es gibt einen Fehlerbericht darüber, der keine hohe Priorität zu haben scheint (berichtet am 5. Juni).

Meine Frage ist also: Gibt es alternative Strategien, die tatsächlich funktionieren? Ich habe den Zwei-Tabellen-Ansatz ausprobiert, aber es ist unmöglich zu garantieren, dass der Header mit dem Inhalt übereinstimmt. Muss ich nur warten, bis das Webkit das Problem behoben hat?

Andrew Ensley
quelle

Antworten:

33

Hier ist ein Arbeitsbeispiel:

http://www.imaputz.com/cssStuff/bigFourVersion.html

Sie müssen den display: block zum thead> tr und tbody hinzufügen

Michael Koper
quelle
@CristianBoariu nicht? :(
Andreas Wong
1
@ Michael Koper Das gefällt mir sehr gut. Leider funktioniert es nicht auf IE9 :(
Mo.
3
Dies schlägt auf IE 9 völlig fehl, die Lösung ist so inho inakzeptabel. Es gibt keinen Fallback, im IE werden überhaupt keine Tabellenzeilen angezeigt!
John
7
Dies funktioniert nur, wenn jede Zelle dieselbe festgelegte Länge hat. Ist es möglich, dass dies mit flexiblen Tabellen funktioniert?
Straßenlaterne
24
Dies ist keine Lösung. Der ganze Punkt von Tabellen besteht darin, Spalten zu haben, die dynamisch an den in der Tabelle angezeigten Datenpunkten ausgerichtet sind. Das Festlegen einer festen Breite für eine Kopfzeile führt schließlich nur zu einer falsch ausgerichteten Tabelle. Der Kampf um die Anzeige richtig tabellarische Daten in einem Browser marschiert ... seufzen
Ravenhurst
17

Verwenden des Blockstils display: funktioniert nur, wenn Sie eine Spalte haben. Wenn Sie mehrere Datenspalten haben - mit mehreren Feldern -, wird angezeigt: Der Block scheint alle Datenspalten scrollbar zu machen, jedoch unter der ersten Spalte (macht dasselbe in Firefox - dem einzigen mir bekannten Browser, der gut scrollen kann). In Firefox können Sie übrigens den Stil overflow-x: hidden verwenden, um den horizontalen Bildlauf zu unterdrücken.

Ich habe festgestellt, dass das erwähnte Problem nur auftritt, wenn Sie keine Breite für die th & td-Elemente angeben. Wenn Sie die Spaltenbreiten korrigieren können, funktioniert es. Das Problem für mich ist, dass ich die Spaltenbreiten nicht korrigieren kann.


quelle
7
"Das Problem für mich ist, dass ich die Spaltenbreiten nicht korrigieren kann." Genau mein Problem. = /
Andrew Ensley
2
Auch für mich nicht in der Lage, die Spaltenbreite zu fixieren
i0707
12

Versuchen Sie die erste Methode dieser Seite, reines CSS mit einer einzelnen Tabelle (2 Divs um die Tabelle, und der Kopf ist absolut positioniert): http://www.cssplay.co.uk/menu/tablescroll.html Scheint zu arbeiten FF4 / IE9 / IE8 zusätzlich zu IE7 / FF3.6.

lsf
quelle
Ich konnte sehr wenig Beschreibung der Schritte finden, um diese Arbeit tatsächlich zu machen. Können Sie näher darauf eingehen?
Benekastah
5

Ich hatte das gleiche Problem und schrieb ein jQuery-Skript, um dies für mich zu tun ... verwendet zwei Tabellenelemente und formatiert das CSS entsprechend. Hoffe das hilft anderen, die das gleiche Problem haben ...

http://jsfiddle.net/pe295/1/

Sean Haddy
quelle
5

Ich habe Sean Haddys hervorragende Lösung gesehen und mir die Freiheit genommen , einige Änderungen vorzunehmen :

  • Verwenden Sie Klassen anstelle von ID, sodass ein jQuery-Skript für mehrere Tabellen auf einer Seite wiederverwendet werden kann
  • Unterstützung für semantische HTML-Tabellenelemente wie caption, thead, tfoot und tbody hinzugefügt
  • Die Bildlaufleiste wurde optional gemacht, sodass sie nicht für Tabellen angezeigt wird, die "kürzer" als die scrollbare Höhe sind
  • Die Breite des Bildlauf-Divs wurde angepasst, um die Bildlaufleiste an den rechten Rand der Tabelle zu bringen
  • Konzept zugänglich gemacht durch
    • Verwenden von aria-hidden = "true" für den injizierten statischen Tabellenheader
    • und den ursprünglichen Kopf an Ort und Stelle belassen, nur mit jQuery versteckt und gesetzt aria-hidden="false"
  • Beispiele für mehrere Tabellen mit unterschiedlichen Größen

Sean machte das schwere Heben. Vielen Dank auch an Matt Burland für den Hinweis, dass der Fuß unterstützt werden muss.

Überzeugen Sie sich selbst unter http://jsfiddle.net/jhfrench/eNP2N/

Jeromy Französisch
quelle
3

A hatte vor langer Zeit das gleiche Problem, und ich habe schließlich den Ansatz mit zwei Tabellen dargelegt. Dies ist das Ergebnis: http://jsfiddle.net/bGr4V/3/ , es funktioniert für alle Browser (IE6 + inkl.).

In dieser jsFiddle können Sie mit einer sauberen Version spielen.

Meine Lösung war eine hinzuzufügen fix Zelle <th class="fix"> </th> in theadfüllen den Raum der Bildlaufleiste in der tbody, dann gibt einer Spalte eine variable Breite ( <td class="grow">), so dass der Kopf fix Zelle würde nicht unmatch auf Größe ändern.

HTML:

<div class="fixed_table">
  <div class="head">
    <table>
      <thead>
        <tr>
          <th>Column header</th>
          <th class="grow">Column header</th>
          <th class="fix"> </th>
        </tr>
      </thead>
    </table>
  <div class="body">
    <table class="full_table">
      <caption class="caption">Caption</caption>
      <tbody>
        <tr>
          <td>Data</td>
          <td class="grow">Data</td>
        </tr>
        <tr>
          <td>...</td>
          <td>...</td>
        </tr>
        <tr>
          <td>...</td>
          <td>...</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

CSS: has *und _hack für ie6-7 und jeweils eine -webkitfür die Header - Fixzelle passende Bildlaufbreite .

.fixed_table table {
  table-layout: fixed;
  width: auto;
  border-width: 0;
  padding: 0;
  border-collapse: collapse;
}

.fixed_table .body {
  overflow: scroll;
  overflow-x: hidden;
  max-height: 10.75em;
  min-height: 2.5em;
  padding-bottom: 0.8em;
  *padding-right: 17px; /*ie7 & ie6*/
  _padding-right: 0; /*ie6*/
  _height: 10em ;
}

.fixed_table th, .fixed_table td {
  width: 4.7em;
}

.fixed_table .grow {
  width: auto;
}

.fixed_table .fix {
  width: 16px;
  *width: 17px; /*ie7 & ie6*/
  _width: 16px; /*ie6*/
}

/* webkit specific */
@media screen and (-webkit-min-device-pixel-ratio:0) {
  .fixed_table .fix{ width: 17px }
}
IG Pascual
quelle
2

Ich dachte, ich würde meine Lösung in den Mix werfen - http://tjvantoll.com/2012/11/10/creating-cross-browser-scrollable-tbody/ .

Es nimmt den gleichen grundlegenden Weg wie die Lösung von @Michael Koper, enthält jedoch eine Problemumgehung, damit die Tabelle im IE wieder korrekt zu IE6 aussieht.

Ich löse das Breitenproblem, indem ich den Zellen in jeder Spalte das <table>a gebe table-layout: fixedund ihnen explizit die Breite zuweise. Nicht ideal, aber es wird eine semantische Tabelle erstellt, die browserübergreifend ausgerichtet wird, unabhängig davon, ob eine Bildlaufleiste benötigt wird.

Demo: http://codepen.io/tjvantoll/pen/JEKIu

TJ VanToll
quelle
1

Ich habe eine Javascript-Lösung für das oben genannte Problem entwickelt,
die nur in Firefox 7+ funktioniert, da ich nur in FF getestet habe.

Ich bin zu diesem Thread gekommen und habe eine Lösung gefunden, auf die Michael Koper hingewiesen hat

In dieser Lösung werden drei wichtige Dinge erledigt:
1)
Festlegen der Spaltenbreite 2) Die Anzeige des Kopfes> tr ist auf Block eingestellt.
3) Die Anzeige des Körpers ist auf Block eingestellt

Wie andere erwähnt haben, gibt es auch Probleme, die Breite zu korrigieren. Ich bin auch in derselben Position.
Selbst ich kann die Breite nicht statisch fixieren

Also dachte ich, ich werde die Breite dynamisch korrigieren (nachdem die Tabelle im Browser gerendert wurde) und das hat den Trick gemacht :)

Das Folgende ist die Lösung in Javascript, die nur in FF funktioniert
(ich habe nur in FF getestet, ich habe keinen Zugriff auf andere Browser)

       function test1(){                
            var tbodys = document.getElementsByTagName("TBODY");
            for(var i=0;i<tbodys.length;i++){
                do_tbodyscroll(tbodys[i]);
            }
        }


      function do_tbodyscroll(_tbody){
            // get the table node 
            var table = _tbody.parentNode;

            // first row of tbody 
            var _fr = _tbody.getElementsByTagName("TR")[0];

            // first row cells .. 
            var _frcells = _fr.cells;

            // Width array , width of each element is stored in this array 
            var widtharray = new Array(_frcells.length);

            for(var i=0;i<_frcells.length;i++){                    
                widtharray[i] = _frcells[i].scrollWidth;
            }                

            // Apply width to first row                  
            for(var i=0;i<_frcells.length;i++){
                _frcells[i].width = widtharray[i];                   
            }                 

            // Get the Last row in Thead ... 
            // COLGROUPS USING COLSPAN NOT YET SUPPORTED

            var thead = table.getElementsByTagName("THEAD")[0];
            var _rows = thead.getElementsByTagName("TR");
            var tableheader = _rows[_rows.length - 1];
            var headercells = tableheader.cells;

            // Apply width to header ..                                
            for(var i=0;i<headercells.length;i++){
                headercells[i].width = widtharray[i];
            }

            // ADD 16 Pixel of scroll bar to last column ..
            headercells[headercells.length -1 ].width = widtharray[headercells.length -1] + 16;

            tableheader.style.display = "block";
            _tbody.style.display = "block";  
        }

Diese Lösung ermittelt die Breite der Spalte im Browser
und setzt erneut die gleiche Breite für die Spalten (Kopfzeile und erste Zeile von tbody).
nachdem die Breite festgelegt wurde. Die Anzeige von head> tr und tbody ist auf Block eingestellt

Ich hoffe, diese Lösung ist für Sie alle nützlich.
Wenn Sie sie auf andere Browser ausweiten können, antworten Sie bitte auf diesen Beitrag

Digambar Sangavkar
quelle
1
Eine wichtige Sache ist, dass jeder Stil haben sollte, in dem die erforderliche Höhe erwähnt wird und der Überlauf als automatisch definiert wird
Digambar Sangavkar
1

Das ist wirklich ziemlich hackig, aber vielleicht hilft es jemandem irgendwo ...

http://jsfiddle.net/yUHCq/1/

Es werden Spalten anstelle von Zeilen verwendet, sodass die Verarbeitung im Wesentlichen rückwärts erfolgt.

Übergangs-DOCTYPE aus Gründen der IE-Kompatibilität hinzugefügt.

Matthew
quelle
5
Werden Leute für so etwas in die CSS-Hölle geschickt?
Matthew
1
Das ist kein <tbody>Element, geschweige denn ein Tabellenelement, und beantwortet daher die Frage nicht (der Titel lässt wenig Raum für Fantasie).
Rob W
1

Es mag für diese Frage übertrieben sein, aber YUI bietet möglicherweise immer noch die beste kostenlose browserübergreifende Datierung. Es kann auch für schreibgeschützte Daten verwendet werden.

YUI 2 DataTable

YUI 3 DataTable

Klicken Sie dort auf die Beispiele, um scrollbare Beispiele anzuzeigen. Da ich ein Neuling im Stackoverflow bin, kann ich nur diese beiden Links posten.

user2030366
quelle
0

Hinzufügen display:block;Dadurch wird auch der unnötige horizontale Bildlauf in FireFox entfernt. Sie wissen zweifellos auch, dass keines der beiden Beispiele in MSIE 8 funktioniert.

<table>
    <thead>
        <tr><th>This is the header and doesn't scroll</th></tr>
    </thead>
    <tbody style="height:100px; overflow:auto;display:block;">
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
        <tr><td>content that scrolls</td></tr>
    </tbody>
</table>
mmcglynn
quelle
6
Mehrere Spalten sind nicht Teil des in der Frage angegebenen Beispiels.
mmcglynn
2
@mmcglynn: Das mag zwar zutreffen, aber der einzige Grund, dies überhaupt tun zu wollen, ist eine mehrspaltige Tabelle, daher ist dies eine faire Annahme. Nehmen Sie nicht alle Fragen zum Nennwert.
Matti Virkkunen
Klar, in Zukunft werde ich Markups hinzufügen, die nicht im Beispiel enthalten sind, und mit Ihrer Interpretation der Frage verweisen.
mmcglynn
0

Wenn jemand es benötigt, um im IE-Mackenmodus zu arbeiten, habe ich den Code von IG Pascual folgendermaßen geändert und vereinfacht:

.fixed_table{
       overflow: scroll;
       overflow-x: hidden;
       max-height: 300px;
       height: 300px;
       min-height: 50px;
       padding-right:0;
}
#datatable td 
{
       padding:3px;
       text-align: center;
       width: 9%;
       vertical-align: middle;
       background-color: #343435; 
       color: #E0E0E3;
       overflow:hidden;
} 
<div class="head">
    <table>
        <thead>
            <tr>
                <th>Time (GMT)</th>
                <th>Price</th>
            </tr>
        </thead>
    </table>
</div>
<div class="fixed_table">
    <table id="datatable" cellspacing="1" cellpadding="1">
        <tbody></tbody>
    </table>
</div>
Ronen Festinger
quelle
0

Lassen Sie die Tabelle so zeichnen, wie sie ist, berechnen Sie die Breite jeder Spalte und setzen Sie sie in jede Überschrift. Überschriften werden mit Unterteilungen erstellt, und dann können wir die Tabelle frei scrollen lassen.

<!DOCTYPE html>
<html>
<head>
<style>
.t_heading{
  margin-top: 20px;
  font-family: Verdana, Geneva, sans-serif;
  background-color: #4CAF50;
}

.heading{
  background-color: #4CAF50;
  color: white;
  float:left;
  padding: 8px 0PX 8PX 0PX;
  border-bottom: 1px solid #ddd;
  height: 20px;
  text-align: left;
}

.t_data{
  overflow-y: scroll;
  overflow-x: hidden;
  height:0px;
  width: 100%;

}

.t_content{
    border-collapse: collapse;
    font-family: Verdana, Geneva, sans-serif;
    width: 100%;
}

.column1,.column2,.column3,.column4{
    padding: 8px 0PX 8PX 0PX;
    text-align: left;
    border-bottom: 1px solid #ddd;
}
.t_row:hover{
  background-color:#f5f5f5;
}
</style>
<script>
function setBody(){
    var body = document.body,
    html = document.documentElement;

    var height = Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight );
    height = height-300;
    /*
     ** By changing the subtraction value, You can fit the table in to the screen correctly.
     ** Make sure not to come the hscroll.
     ** Or you can set fixed height with css for the div as your wish.
     */
    document.getElementById("t_data").style.height = height+"px";

    setColumnWidth("column1");
    setColumnWidth("column2");
    setColumnWidth("column3");
    setColumnWidth("column4");
}

function setColumnWidth(o){
        var object = o;
        var x = document.getElementsByClassName(object);
        var y = x[0].clientWidth;
        document.getElementById(object).style.width = y+"px";
 }
</script>
</head>

<body onload="setBody()">
<div class="t_heading">
<div class="heading"  id="column1">Heading 1</div>
<div class="heading"  id="column2">Heading 2</div>
<div class="heading"  id="column3">Heading 3</div>
<div class="heading"  id="column4">Heading 4</div>
</div>
<div class="t_data" id="t_data">
<table class="t_content">
    <tr class='t_row'>
        <td class='column1'>Column1 Row 0</td>
        <td class='column2'>Column2 Row 0</td>
        <td class='column3'>Column3 Row 0</td>
        <td class='column4'>Column4 Row 0</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 1</td>
        <td class='column2'>Column2 Row 1</td>
        <td class='column3'>Column3 Row 1</td>
        <td class='column4'>Column4 Row 1</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 2</td>
        <td class='column2'>Column2 Row 2</td>
        <td class='column3'>Column3 Row 2</td>
        <td class='column4'>Column4 Row 2</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 3</td>
        <td class='column2'>Column2 Row 3</td>
        <td class='column3'>Column3 Row 3</td>
        <td class='column4'>Column4 Row 3</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 4</td>
        <td class='column2'>Column2 Row 4</td>
        <td class='column3'>Column3 Row 4</td>
        <td class='column4'>Column4 Row 4</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 5</td>
        <td class='column2'>Column2 Row 5</td>
        <td class='column3'>Column3 Row 5</td>
        <td class='column4'>Column4 Row 5</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 6</td>
        <td class='column2'>Column2 Row 6</td>
        <td class='column3'>Column3 Row 6</td>
        <td class='column4'>Column4 Row 6</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 7</td>
        <td class='column2'>Column2 Row 7</td>
        <td class='column3'>Column3 Row 7</td>
        <td class='column4'>Column4 Row 7</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 8</td>
        <td class='column2'>Column2 Row 8</td>
        <td class='column3'>Column3 Row 8</td>
        <td class='column4'>Column4 Row 8</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 9</td>
        <td class='column2'>Column2 Row 9</td>
        <td class='column3'>Column3 Row 9</td>
        <td class='column4'>Column4 Row 9</td>
    </tr><tr class='t_row'>
        <td class='column1'>Column1 Row 10</td>
        <td class='column2'>Column2 Row 10</td>
        <td class='column3'>Column3 Row 10</td>
        <td class='column4'>Column4 Row 10</td>
    </tr>
<!--
<?php
$data = array();
for($a = 0; $a<50; $a++)
{
    $data[$a] = array();
    $data[$a][0] = "Column1 Row ".$a;
    $data[$a][1] = "Column2 Row ".$a;
    $data[$a][2] = "Column3 Row ".$a;
    $data[$a][3] = "Column4 Row ".$a;
}
/*
 ** supose you have data in an array.. which red from database. The table will draw using array data. Or you can draw the table manualy.
 ** tip: If using manual table, No need of
 ** 'var x = document.getElementsByClassName(object); var y = x[0].clientWidth;'.
 ** You can just set ID of first row's cells in to some name and use it to read width.
 */
for($i=0;$i<sizeof($data);$i++){
    echo "<tr class='t_row'><td class='column1'>".$data[$i][0]."</td><td class='column2'>".$data[$i][1]."</td><td class='column3'>".$data[$i][2]."</td><td class='column4'>".$data[$i][3]."</td></tr>";
}
?>
-->
</table>
</div>
</body>
</html>
Salitha Prasad
quelle